Properly access a buffer's LSN using existing access macros instead of abusing
[PostgreSQL.git] / src / backend / utils / adt / pgstatfuncs.c
blob77c2baa98f81e94ce3251844253dc5ee3826608e
1 /*-------------------------------------------------------------------------
3 * pgstatfuncs.c
4 * Functions for accessing the statistics collector data
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
15 #include "postgres.h"
17 #include "funcapi.h"
18 #include "miscadmin.h"
19 #include "pgstat.h"
20 #include "catalog/pg_type.h"
21 #include "utils/builtins.h"
22 #include "utils/inet.h"
23 #include "libpq/ip.h"
25 /* bogus ... these externs should be in a header file */
26 extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS);
27 extern Datum pg_stat_get_tuples_returned(PG_FUNCTION_ARGS);
28 extern Datum pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS);
29 extern Datum pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS);
30 extern Datum pg_stat_get_tuples_updated(PG_FUNCTION_ARGS);
31 extern Datum pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS);
32 extern Datum pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS);
33 extern Datum pg_stat_get_live_tuples(PG_FUNCTION_ARGS);
34 extern Datum pg_stat_get_dead_tuples(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_function_calls(PG_FUNCTION_ARGS);
43 extern Datum pg_stat_get_function_time(PG_FUNCTION_ARGS);
44 extern Datum pg_stat_get_function_self_time(PG_FUNCTION_ARGS);
46 extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
47 extern Datum pg_stat_get_activity(PG_FUNCTION_ARGS);
48 extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
49 extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
50 extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
51 extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
52 extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
53 extern Datum pg_stat_get_backend_waiting(PG_FUNCTION_ARGS);
54 extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
55 extern Datum pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS);
56 extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
57 extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
58 extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
60 extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
61 extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
62 extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
63 extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
64 extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
65 extern Datum pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS);
66 extern Datum pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS);
67 extern Datum pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS);
68 extern Datum pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS);
69 extern Datum pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS);
71 extern Datum pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS);
72 extern Datum pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS);
73 extern Datum pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS);
74 extern Datum pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS);
75 extern Datum pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS);
76 extern Datum pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS);
77 extern Datum pg_stat_get_buf_alloc(PG_FUNCTION_ARGS);
79 extern Datum pg_stat_clear_snapshot(PG_FUNCTION_ARGS);
80 extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
82 /* Global bgwriter statistics, from bgwriter.c */
83 extern PgStat_MsgBgWriter bgwriterStats;
85 Datum
86 pg_stat_get_numscans(PG_FUNCTION_ARGS)
88 Oid relid = PG_GETARG_OID(0);
89 int64 result;
90 PgStat_StatTabEntry *tabentry;
92 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
93 result = 0;
94 else
95 result = (int64) (tabentry->numscans);
97 PG_RETURN_INT64(result);
101 Datum
102 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
104 Oid relid = PG_GETARG_OID(0);
105 int64 result;
106 PgStat_StatTabEntry *tabentry;
108 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
109 result = 0;
110 else
111 result = (int64) (tabentry->tuples_returned);
113 PG_RETURN_INT64(result);
117 Datum
118 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
120 Oid relid = PG_GETARG_OID(0);
121 int64 result;
122 PgStat_StatTabEntry *tabentry;
124 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
125 result = 0;
126 else
127 result = (int64) (tabentry->tuples_fetched);
129 PG_RETURN_INT64(result);
133 Datum
134 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
136 Oid relid = PG_GETARG_OID(0);
137 int64 result;
138 PgStat_StatTabEntry *tabentry;
140 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
141 result = 0;
142 else
143 result = (int64) (tabentry->tuples_inserted);
145 PG_RETURN_INT64(result);
149 Datum
150 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
152 Oid relid = PG_GETARG_OID(0);
153 int64 result;
154 PgStat_StatTabEntry *tabentry;
156 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
157 result = 0;
158 else
159 result = (int64) (tabentry->tuples_updated);
161 PG_RETURN_INT64(result);
165 Datum
166 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
168 Oid relid = PG_GETARG_OID(0);
169 int64 result;
170 PgStat_StatTabEntry *tabentry;
172 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
173 result = 0;
174 else
175 result = (int64) (tabentry->tuples_deleted);
177 PG_RETURN_INT64(result);
181 Datum
182 pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
184 Oid relid = PG_GETARG_OID(0);
185 int64 result;
186 PgStat_StatTabEntry *tabentry;
188 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
189 result = 0;
190 else
191 result = (int64) (tabentry->tuples_hot_updated);
193 PG_RETURN_INT64(result);
197 Datum
198 pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
200 Oid relid = PG_GETARG_OID(0);
201 int64 result;
202 PgStat_StatTabEntry *tabentry;
204 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
205 result = 0;
206 else
207 result = (int64) (tabentry->n_live_tuples);
209 PG_RETURN_INT64(result);
213 Datum
214 pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
216 Oid relid = PG_GETARG_OID(0);
217 int64 result;
218 PgStat_StatTabEntry *tabentry;
220 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
221 result = 0;
222 else
223 result = (int64) (tabentry->n_dead_tuples);
225 PG_RETURN_INT64(result);
229 Datum
230 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
232 Oid relid = PG_GETARG_OID(0);
233 int64 result;
234 PgStat_StatTabEntry *tabentry;
236 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
237 result = 0;
238 else
239 result = (int64) (tabentry->blocks_fetched);
241 PG_RETURN_INT64(result);
245 Datum
246 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
248 Oid relid = PG_GETARG_OID(0);
249 int64 result;
250 PgStat_StatTabEntry *tabentry;
252 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
253 result = 0;
254 else
255 result = (int64) (tabentry->blocks_hit);
257 PG_RETURN_INT64(result);
260 Datum
261 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
263 Oid relid = PG_GETARG_OID(0);
264 TimestampTz result;
265 PgStat_StatTabEntry *tabentry;
267 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
268 result = 0;
269 else
270 result = tabentry->vacuum_timestamp;
272 if (result == 0)
273 PG_RETURN_NULL();
274 else
275 PG_RETURN_TIMESTAMPTZ(result);
278 Datum
279 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
281 Oid relid = PG_GETARG_OID(0);
282 TimestampTz result;
283 PgStat_StatTabEntry *tabentry;
285 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
286 result = 0;
287 else
288 result = tabentry->autovac_vacuum_timestamp;
290 if (result == 0)
291 PG_RETURN_NULL();
292 else
293 PG_RETURN_TIMESTAMPTZ(result);
296 Datum
297 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
299 Oid relid = PG_GETARG_OID(0);
300 TimestampTz result;
301 PgStat_StatTabEntry *tabentry;
303 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
304 result = 0;
305 else
306 result = tabentry->analyze_timestamp;
308 if (result == 0)
309 PG_RETURN_NULL();
310 else
311 PG_RETURN_TIMESTAMPTZ(result);
314 Datum
315 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
317 Oid relid = PG_GETARG_OID(0);
318 TimestampTz result;
319 PgStat_StatTabEntry *tabentry;
321 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
322 result = 0;
323 else
324 result = tabentry->autovac_analyze_timestamp;
326 if (result == 0)
327 PG_RETURN_NULL();
328 else
329 PG_RETURN_TIMESTAMPTZ(result);
332 Datum
333 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
335 Oid funcid = PG_GETARG_OID(0);
336 PgStat_StatFuncEntry *funcentry;
338 if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
339 PG_RETURN_NULL();
340 PG_RETURN_INT64(funcentry->f_numcalls);
343 Datum
344 pg_stat_get_function_time(PG_FUNCTION_ARGS)
346 Oid funcid = PG_GETARG_OID(0);
347 PgStat_StatFuncEntry *funcentry;
349 if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
350 PG_RETURN_NULL();
351 PG_RETURN_INT64(funcentry->f_time);
354 Datum
355 pg_stat_get_function_self_time(PG_FUNCTION_ARGS)
357 Oid funcid = PG_GETARG_OID(0);
358 PgStat_StatFuncEntry *funcentry;
360 if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
361 PG_RETURN_NULL();
362 PG_RETURN_INT64(funcentry->f_time_self);
365 Datum
366 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
368 FuncCallContext *funcctx;
369 int *fctx;
370 int32 result;
372 /* stuff done only on the first call of the function */
373 if (SRF_IS_FIRSTCALL())
375 /* create a function context for cross-call persistence */
376 funcctx = SRF_FIRSTCALL_INIT();
378 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
379 2 * sizeof(int));
380 funcctx->user_fctx = fctx;
382 fctx[0] = 0;
383 fctx[1] = pgstat_fetch_stat_numbackends();
386 /* stuff done on every call of the function */
387 funcctx = SRF_PERCALL_SETUP();
388 fctx = funcctx->user_fctx;
390 fctx[0] += 1;
391 result = fctx[0];
393 if (result <= fctx[1])
395 /* do when there is more left to send */
396 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
398 else
400 /* do when there is no more left */
401 SRF_RETURN_DONE(funcctx);
405 Datum
406 pg_stat_get_activity(PG_FUNCTION_ARGS)
408 FuncCallContext *funcctx;
410 if (SRF_IS_FIRSTCALL())
412 MemoryContext oldcontext;
413 TupleDesc tupdesc;
415 funcctx = SRF_FIRSTCALL_INIT();
417 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
419 tupdesc = CreateTemplateTupleDesc(10, false);
420 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0);
421 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid", INT4OID, -1, 0);
422 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid", OIDOID, -1, 0);
423 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "current_query", TEXTOID, -1, 0);
424 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "waiting", BOOLOID, -1, 0);
425 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "act_start", TIMESTAMPTZOID, -1, 0);
426 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "query_start", TIMESTAMPTZOID, -1, 0);
427 TupleDescInitEntry(tupdesc, (AttrNumber) 8, "backend_start", TIMESTAMPTZOID, -1, 0);
428 TupleDescInitEntry(tupdesc, (AttrNumber) 9, "client_addr", INETOID, -1, 0);
429 TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_port", INT4OID, -1, 0);
431 funcctx->tuple_desc = BlessTupleDesc(tupdesc);
433 funcctx->user_fctx = palloc0(sizeof(int));
434 if (PG_ARGISNULL(0))
436 /* Get all backends */
437 funcctx->max_calls = pgstat_fetch_stat_numbackends();
439 else
442 * Get one backend - locate by pid.
444 * We lookup the backend early, so we can return zero rows if it doesn't
445 * exist, instead of returning a single row full of NULLs.
447 int pid = PG_GETARG_INT32(0);
448 int i;
449 int n = pgstat_fetch_stat_numbackends();
451 for (i = 1; i <= n; i++)
453 PgBackendStatus *be = pgstat_fetch_stat_beentry(i);
454 if (be)
456 if (be->st_procpid == pid)
458 *(int *)(funcctx->user_fctx) = i;
459 break;
464 if (*(int *)(funcctx->user_fctx) == 0)
465 /* Pid not found, return zero rows */
466 funcctx->max_calls = 0;
467 else
468 funcctx->max_calls = 1;
471 MemoryContextSwitchTo(oldcontext);
474 /* stuff done on every call of the function */
475 funcctx = SRF_PERCALL_SETUP();
477 if (funcctx->call_cntr < funcctx->max_calls)
479 /* for each row */
480 Datum values[10];
481 bool nulls[10];
482 HeapTuple tuple;
483 PgBackendStatus *beentry;
484 SockAddr zero_clientaddr;
486 MemSet(values, 0, sizeof(values));
487 MemSet(nulls, 0, sizeof(nulls));
489 if (*(int *)(funcctx->user_fctx) > 0)
490 /* Get specific pid slot */
491 beentry = pgstat_fetch_stat_beentry(*(int *)(funcctx->user_fctx));
492 else
493 /* Get the next one in the list */
494 beentry = pgstat_fetch_stat_beentry(funcctx->call_cntr+1); /* 1-based index */
495 if (!beentry)
497 int i;
499 for (i = 0; i < sizeof(nulls)/sizeof(nulls[0]); i++)
500 nulls[i] = true;
502 nulls[3] = false;
503 values[3] = CStringGetTextDatum("<backend information not available>");
505 tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
506 SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
509 /* Values available to all callers */
510 values[0] = ObjectIdGetDatum(beentry->st_databaseid);
511 values[1] = Int32GetDatum(beentry->st_procpid);
512 values[2] = ObjectIdGetDatum(beentry->st_userid);
514 /* Values only available to same user or superuser */
515 if (superuser() || beentry->st_userid == GetUserId())
517 if (*(beentry->st_activity) == '\0')
519 values[3] = CStringGetTextDatum("<command string not enabled>");
521 else
523 values[3] = CStringGetTextDatum(beentry->st_activity);
526 values[4] = BoolGetDatum(beentry->st_waiting);
528 if (beentry->st_xact_start_timestamp != 0)
529 values[5] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
530 else
531 nulls[5] = true;
533 if (beentry->st_activity_start_timestamp != 0)
534 values[6] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
535 else
536 nulls[6] = true;
538 if (beentry->st_proc_start_timestamp != 0)
539 values[7] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
540 else
541 nulls[7] = true;
543 /* A zeroed client addr means we don't know */
544 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
545 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
546 sizeof(zero_clientaddr) == 0))
548 nulls[8] = true;
549 nulls[9] = true;
551 else
553 if (beentry->st_clientaddr.addr.ss_family == AF_INET
554 #ifdef HAVE_IPV6
555 || beentry->st_clientaddr.addr.ss_family == AF_INET6
556 #endif
559 char remote_host[NI_MAXHOST];
560 char remote_port[NI_MAXSERV];
561 int ret;
563 remote_host[0] = '\0';
564 remote_port[0] = '\0';
565 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
566 beentry->st_clientaddr.salen,
567 remote_host, sizeof(remote_host),
568 remote_port, sizeof(remote_port),
569 NI_NUMERICHOST | NI_NUMERICSERV);
570 if (ret)
572 nulls[8] = true;
573 nulls[9] = true;
575 else
577 clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
578 values[8] = DirectFunctionCall1(inet_in,
579 CStringGetDatum(remote_host));
580 values[9] = Int32GetDatum(atoi(remote_port));
583 else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
586 * Unix sockets always reports NULL for host and -1 for port, so it's
587 * possible to tell the difference to connections we have no
588 * permissions to view, or with errors.
590 nulls[8] = true;
591 values[9] = DatumGetInt32(-1);
593 else
595 /* Unknown address type, should never happen */
596 nulls[8] = true;
597 nulls[9] = true;
601 else
603 /* No permissions to view data about this session */
604 values[3] = CStringGetTextDatum("<insufficient privilege>");
605 nulls[4] = true;
606 nulls[5] = true;
607 nulls[6] = true;
608 nulls[7] = true;
609 nulls[8] = true;
610 nulls[9] = true;
613 tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
615 SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
617 else
619 /* nothing left */
620 SRF_RETURN_DONE(funcctx);
625 Datum
626 pg_backend_pid(PG_FUNCTION_ARGS)
628 PG_RETURN_INT32(MyProcPid);
632 Datum
633 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
635 int32 beid = PG_GETARG_INT32(0);
636 PgBackendStatus *beentry;
638 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
639 PG_RETURN_NULL();
641 PG_RETURN_INT32(beentry->st_procpid);
645 Datum
646 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
648 int32 beid = PG_GETARG_INT32(0);
649 PgBackendStatus *beentry;
651 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
652 PG_RETURN_NULL();
654 PG_RETURN_OID(beentry->st_databaseid);
658 Datum
659 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
661 int32 beid = PG_GETARG_INT32(0);
662 PgBackendStatus *beentry;
664 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
665 PG_RETURN_NULL();
667 PG_RETURN_OID(beentry->st_userid);
671 Datum
672 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
674 int32 beid = PG_GETARG_INT32(0);
675 PgBackendStatus *beentry;
676 const char *activity;
678 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
679 activity = "<backend information not available>";
680 else if (!superuser() && beentry->st_userid != GetUserId())
681 activity = "<insufficient privilege>";
682 else if (*(beentry->st_activity) == '\0')
683 activity = "<command string not enabled>";
684 else
685 activity = beentry->st_activity;
687 PG_RETURN_TEXT_P(cstring_to_text(activity));
691 Datum
692 pg_stat_get_backend_waiting(PG_FUNCTION_ARGS)
694 int32 beid = PG_GETARG_INT32(0);
695 bool result;
696 PgBackendStatus *beentry;
698 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
699 PG_RETURN_NULL();
701 if (!superuser() && beentry->st_userid != GetUserId())
702 PG_RETURN_NULL();
704 result = beentry->st_waiting;
706 PG_RETURN_BOOL(result);
710 Datum
711 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
713 int32 beid = PG_GETARG_INT32(0);
714 TimestampTz result;
715 PgBackendStatus *beentry;
717 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
718 PG_RETURN_NULL();
720 if (!superuser() && beentry->st_userid != GetUserId())
721 PG_RETURN_NULL();
723 result = beentry->st_activity_start_timestamp;
726 * No time recorded for start of current query -- this is the case if the
727 * user hasn't enabled query-level stats collection.
729 if (result == 0)
730 PG_RETURN_NULL();
732 PG_RETURN_TIMESTAMPTZ(result);
736 Datum
737 pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS)
739 int32 beid = PG_GETARG_INT32(0);
740 TimestampTz result;
741 PgBackendStatus *beentry;
743 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
744 PG_RETURN_NULL();
746 if (!superuser() && beentry->st_userid != GetUserId())
747 PG_RETURN_NULL();
749 result = beentry->st_xact_start_timestamp;
751 if (result == 0) /* not in a transaction */
752 PG_RETURN_NULL();
754 PG_RETURN_TIMESTAMPTZ(result);
758 Datum
759 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
761 int32 beid = PG_GETARG_INT32(0);
762 TimestampTz result;
763 PgBackendStatus *beentry;
765 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
766 PG_RETURN_NULL();
768 if (!superuser() && beentry->st_userid != GetUserId())
769 PG_RETURN_NULL();
771 result = beentry->st_proc_start_timestamp;
773 if (result == 0) /* probably can't happen? */
774 PG_RETURN_NULL();
776 PG_RETURN_TIMESTAMPTZ(result);
780 Datum
781 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
783 int32 beid = PG_GETARG_INT32(0);
784 PgBackendStatus *beentry;
785 SockAddr zero_clientaddr;
786 char remote_host[NI_MAXHOST];
787 int ret;
789 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
790 PG_RETURN_NULL();
792 if (!superuser() && beentry->st_userid != GetUserId())
793 PG_RETURN_NULL();
795 /* A zeroed client addr means we don't know */
796 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
797 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
798 sizeof(zero_clientaddr) == 0))
799 PG_RETURN_NULL();
801 switch (beentry->st_clientaddr.addr.ss_family)
803 case AF_INET:
804 #ifdef HAVE_IPV6
805 case AF_INET6:
806 #endif
807 break;
808 default:
809 PG_RETURN_NULL();
812 remote_host[0] = '\0';
813 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
814 beentry->st_clientaddr.salen,
815 remote_host, sizeof(remote_host),
816 NULL, 0,
817 NI_NUMERICHOST | NI_NUMERICSERV);
818 if (ret)
819 PG_RETURN_NULL();
821 clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
823 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
824 CStringGetDatum(remote_host)));
827 Datum
828 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
830 int32 beid = PG_GETARG_INT32(0);
831 PgBackendStatus *beentry;
832 SockAddr zero_clientaddr;
833 char remote_port[NI_MAXSERV];
834 int ret;
836 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
837 PG_RETURN_NULL();
839 if (!superuser() && beentry->st_userid != GetUserId())
840 PG_RETURN_NULL();
842 /* A zeroed client addr means we don't know */
843 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
844 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
845 sizeof(zero_clientaddr) == 0))
846 PG_RETURN_NULL();
848 switch (beentry->st_clientaddr.addr.ss_family)
850 case AF_INET:
851 #ifdef HAVE_IPV6
852 case AF_INET6:
853 #endif
854 break;
855 case AF_UNIX:
856 PG_RETURN_INT32(-1);
857 default:
858 PG_RETURN_NULL();
861 remote_port[0] = '\0';
862 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
863 beentry->st_clientaddr.salen,
864 NULL, 0,
865 remote_port, sizeof(remote_port),
866 NI_NUMERICHOST | NI_NUMERICSERV);
867 if (ret)
868 PG_RETURN_NULL();
870 PG_RETURN_DATUM(DirectFunctionCall1(int4in,
871 CStringGetDatum(remote_port)));
875 Datum
876 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
878 Oid dbid = PG_GETARG_OID(0);
879 int32 result;
880 int tot_backends = pgstat_fetch_stat_numbackends();
881 int beid;
883 result = 0;
884 for (beid = 1; beid <= tot_backends; beid++)
886 PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
888 if (beentry && beentry->st_databaseid == dbid)
889 result++;
892 PG_RETURN_INT32(result);
896 Datum
897 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
899 Oid dbid = PG_GETARG_OID(0);
900 int64 result;
901 PgStat_StatDBEntry *dbentry;
903 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
904 result = 0;
905 else
906 result = (int64) (dbentry->n_xact_commit);
908 PG_RETURN_INT64(result);
912 Datum
913 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
915 Oid dbid = PG_GETARG_OID(0);
916 int64 result;
917 PgStat_StatDBEntry *dbentry;
919 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
920 result = 0;
921 else
922 result = (int64) (dbentry->n_xact_rollback);
924 PG_RETURN_INT64(result);
928 Datum
929 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
931 Oid dbid = PG_GETARG_OID(0);
932 int64 result;
933 PgStat_StatDBEntry *dbentry;
935 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
936 result = 0;
937 else
938 result = (int64) (dbentry->n_blocks_fetched);
940 PG_RETURN_INT64(result);
944 Datum
945 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
947 Oid dbid = PG_GETARG_OID(0);
948 int64 result;
949 PgStat_StatDBEntry *dbentry;
951 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
952 result = 0;
953 else
954 result = (int64) (dbentry->n_blocks_hit);
956 PG_RETURN_INT64(result);
960 Datum
961 pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS)
963 Oid dbid = PG_GETARG_OID(0);
964 int64 result;
965 PgStat_StatDBEntry *dbentry;
967 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
968 result = 0;
969 else
970 result = (int64) (dbentry->n_tuples_returned);
972 PG_RETURN_INT64(result);
976 Datum
977 pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS)
979 Oid dbid = PG_GETARG_OID(0);
980 int64 result;
981 PgStat_StatDBEntry *dbentry;
983 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
984 result = 0;
985 else
986 result = (int64) (dbentry->n_tuples_fetched);
988 PG_RETURN_INT64(result);
992 Datum
993 pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS)
995 Oid dbid = PG_GETARG_OID(0);
996 int64 result;
997 PgStat_StatDBEntry *dbentry;
999 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1000 result = 0;
1001 else
1002 result = (int64) (dbentry->n_tuples_inserted);
1004 PG_RETURN_INT64(result);
1008 Datum
1009 pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS)
1011 Oid dbid = PG_GETARG_OID(0);
1012 int64 result;
1013 PgStat_StatDBEntry *dbentry;
1015 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1016 result = 0;
1017 else
1018 result = (int64) (dbentry->n_tuples_updated);
1020 PG_RETURN_INT64(result);
1024 Datum
1025 pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS)
1027 Oid dbid = PG_GETARG_OID(0);
1028 int64 result;
1029 PgStat_StatDBEntry *dbentry;
1031 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1032 result = 0;
1033 else
1034 result = (int64) (dbentry->n_tuples_deleted);
1036 PG_RETURN_INT64(result);
1039 Datum
1040 pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
1042 PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints);
1045 Datum
1046 pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS)
1048 PG_RETURN_INT64(pgstat_fetch_global()->requested_checkpoints);
1051 Datum
1052 pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS)
1054 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_checkpoints);
1057 Datum
1058 pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS)
1060 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_clean);
1063 Datum
1064 pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS)
1066 PG_RETURN_INT64(pgstat_fetch_global()->maxwritten_clean);
1069 Datum
1070 pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS)
1072 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_backend);
1075 Datum
1076 pg_stat_get_buf_alloc(PG_FUNCTION_ARGS)
1078 PG_RETURN_INT64(pgstat_fetch_global()->buf_alloc);
1082 /* Discard the active statistics snapshot */
1083 Datum
1084 pg_stat_clear_snapshot(PG_FUNCTION_ARGS)
1086 pgstat_clear_snapshot();
1088 PG_RETURN_VOID();
1092 /* Reset all counters for the current database */
1093 Datum
1094 pg_stat_reset(PG_FUNCTION_ARGS)
1096 pgstat_reset_counters();
1098 PG_RETURN_VOID();