]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/pgstatfuncs.c
Add new buffers_backend_fsync field to pg_stat_bgwriter.
[postgresql] / src / backend / utils / adt / pgstatfuncs.c
1 /*-------------------------------------------------------------------------
2  *
3  * pgstatfuncs.c
4  *        Functions for accessing the statistics collector data
5  *
6  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/utils/adt/pgstatfuncs.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
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"
24
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);
41 extern Datum pg_stat_get_vacuum_count(PG_FUNCTION_ARGS);
42 extern Datum pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS);
43 extern Datum pg_stat_get_analyze_count(PG_FUNCTION_ARGS);
44 extern Datum pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS);
45
46 extern Datum pg_stat_get_function_calls(PG_FUNCTION_ARGS);
47 extern Datum pg_stat_get_function_time(PG_FUNCTION_ARGS);
48 extern Datum pg_stat_get_function_self_time(PG_FUNCTION_ARGS);
49
50 extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
51 extern Datum pg_stat_get_activity(PG_FUNCTION_ARGS);
52 extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
53 extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
54 extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
55 extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
56 extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
57 extern Datum pg_stat_get_backend_waiting(PG_FUNCTION_ARGS);
58 extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
59 extern Datum pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS);
60 extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
61 extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
62 extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
63
64 extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
65 extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
66 extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
67 extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
68 extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
69 extern Datum pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS);
70 extern Datum pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS);
71 extern Datum pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS);
72 extern Datum pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS);
73 extern Datum pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS);
74
75 extern Datum pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS);
76 extern Datum pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS);
77 extern Datum pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS);
78 extern Datum pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS);
79 extern Datum pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS);
80 extern Datum pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS);
81 extern Datum pg_stat_get_buf_fsync_backend(PG_FUNCTION_ARGS);
82 extern Datum pg_stat_get_buf_alloc(PG_FUNCTION_ARGS);
83
84 extern Datum pg_stat_get_xact_numscans(PG_FUNCTION_ARGS);
85 extern Datum pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS);
86 extern Datum pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS);
87 extern Datum pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS);
88 extern Datum pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS);
89 extern Datum pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS);
90 extern Datum pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS);
91 extern Datum pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS);
92 extern Datum pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS);
93
94 extern Datum pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS);
95 extern Datum pg_stat_get_xact_function_time(PG_FUNCTION_ARGS);
96 extern Datum pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS);
97
98 extern Datum pg_stat_clear_snapshot(PG_FUNCTION_ARGS);
99 extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
100 extern Datum pg_stat_reset_shared(PG_FUNCTION_ARGS);
101 extern Datum pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS);
102 extern Datum pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS);
103
104 /* Global bgwriter statistics, from bgwriter.c */
105 extern PgStat_MsgBgWriter bgwriterStats;
106
107 Datum
108 pg_stat_get_numscans(PG_FUNCTION_ARGS)
109 {
110         Oid                     relid = PG_GETARG_OID(0);
111         int64           result;
112         PgStat_StatTabEntry *tabentry;
113
114         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
115                 result = 0;
116         else
117                 result = (int64) (tabentry->numscans);
118
119         PG_RETURN_INT64(result);
120 }
121
122
123 Datum
124 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
125 {
126         Oid                     relid = PG_GETARG_OID(0);
127         int64           result;
128         PgStat_StatTabEntry *tabentry;
129
130         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
131                 result = 0;
132         else
133                 result = (int64) (tabentry->tuples_returned);
134
135         PG_RETURN_INT64(result);
136 }
137
138
139 Datum
140 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
141 {
142         Oid                     relid = PG_GETARG_OID(0);
143         int64           result;
144         PgStat_StatTabEntry *tabentry;
145
146         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
147                 result = 0;
148         else
149                 result = (int64) (tabentry->tuples_fetched);
150
151         PG_RETURN_INT64(result);
152 }
153
154
155 Datum
156 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
157 {
158         Oid                     relid = PG_GETARG_OID(0);
159         int64           result;
160         PgStat_StatTabEntry *tabentry;
161
162         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
163                 result = 0;
164         else
165                 result = (int64) (tabentry->tuples_inserted);
166
167         PG_RETURN_INT64(result);
168 }
169
170
171 Datum
172 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
173 {
174         Oid                     relid = PG_GETARG_OID(0);
175         int64           result;
176         PgStat_StatTabEntry *tabentry;
177
178         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
179                 result = 0;
180         else
181                 result = (int64) (tabentry->tuples_updated);
182
183         PG_RETURN_INT64(result);
184 }
185
186
187 Datum
188 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
189 {
190         Oid                     relid = PG_GETARG_OID(0);
191         int64           result;
192         PgStat_StatTabEntry *tabentry;
193
194         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
195                 result = 0;
196         else
197                 result = (int64) (tabentry->tuples_deleted);
198
199         PG_RETURN_INT64(result);
200 }
201
202
203 Datum
204 pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
205 {
206         Oid                     relid = PG_GETARG_OID(0);
207         int64           result;
208         PgStat_StatTabEntry *tabentry;
209
210         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
211                 result = 0;
212         else
213                 result = (int64) (tabentry->tuples_hot_updated);
214
215         PG_RETURN_INT64(result);
216 }
217
218
219 Datum
220 pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
221 {
222         Oid                     relid = PG_GETARG_OID(0);
223         int64           result;
224         PgStat_StatTabEntry *tabentry;
225
226         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
227                 result = 0;
228         else
229                 result = (int64) (tabentry->n_live_tuples);
230
231         PG_RETURN_INT64(result);
232 }
233
234
235 Datum
236 pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
237 {
238         Oid                     relid = PG_GETARG_OID(0);
239         int64           result;
240         PgStat_StatTabEntry *tabentry;
241
242         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
243                 result = 0;
244         else
245                 result = (int64) (tabentry->n_dead_tuples);
246
247         PG_RETURN_INT64(result);
248 }
249
250
251 Datum
252 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
253 {
254         Oid                     relid = PG_GETARG_OID(0);
255         int64           result;
256         PgStat_StatTabEntry *tabentry;
257
258         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
259                 result = 0;
260         else
261                 result = (int64) (tabentry->blocks_fetched);
262
263         PG_RETURN_INT64(result);
264 }
265
266
267 Datum
268 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
269 {
270         Oid                     relid = PG_GETARG_OID(0);
271         int64           result;
272         PgStat_StatTabEntry *tabentry;
273
274         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
275                 result = 0;
276         else
277                 result = (int64) (tabentry->blocks_hit);
278
279         PG_RETURN_INT64(result);
280 }
281
282 Datum
283 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
284 {
285         Oid                     relid = PG_GETARG_OID(0);
286         TimestampTz result;
287         PgStat_StatTabEntry *tabentry;
288
289         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
290                 result = 0;
291         else
292                 result = tabentry->vacuum_timestamp;
293
294         if (result == 0)
295                 PG_RETURN_NULL();
296         else
297                 PG_RETURN_TIMESTAMPTZ(result);
298 }
299
300 Datum
301 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
302 {
303         Oid                     relid = PG_GETARG_OID(0);
304         TimestampTz result;
305         PgStat_StatTabEntry *tabentry;
306
307         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
308                 result = 0;
309         else
310                 result = tabentry->autovac_vacuum_timestamp;
311
312         if (result == 0)
313                 PG_RETURN_NULL();
314         else
315                 PG_RETURN_TIMESTAMPTZ(result);
316 }
317
318 Datum
319 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
320 {
321         Oid                     relid = PG_GETARG_OID(0);
322         TimestampTz result;
323         PgStat_StatTabEntry *tabentry;
324
325         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
326                 result = 0;
327         else
328                 result = tabentry->analyze_timestamp;
329
330         if (result == 0)
331                 PG_RETURN_NULL();
332         else
333                 PG_RETURN_TIMESTAMPTZ(result);
334 }
335
336 Datum
337 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
338 {
339         Oid                     relid = PG_GETARG_OID(0);
340         TimestampTz result;
341         PgStat_StatTabEntry *tabentry;
342
343         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
344                 result = 0;
345         else
346                 result = tabentry->autovac_analyze_timestamp;
347
348         if (result == 0)
349                 PG_RETURN_NULL();
350         else
351                 PG_RETURN_TIMESTAMPTZ(result);
352 }
353
354 Datum
355 pg_stat_get_vacuum_count(PG_FUNCTION_ARGS)
356 {
357         Oid                     relid = PG_GETARG_OID(0);
358         int64           result;
359         PgStat_StatTabEntry     *tabentry;
360
361         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
362                 result = 0;
363         else
364                 result = (int64) (tabentry->vacuum_count);
365
366         PG_RETURN_INT64(result);
367 }
368
369 Datum
370 pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS)
371 {
372         Oid                     relid = PG_GETARG_OID(0);
373         int64           result;
374         PgStat_StatTabEntry     *tabentry;
375
376         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
377                 result = 0;
378         else
379                 result = (int64) (tabentry->autovac_vacuum_count);
380
381         PG_RETURN_INT64(result);
382 }
383
384 Datum
385 pg_stat_get_analyze_count(PG_FUNCTION_ARGS)
386 {
387         Oid                     relid = PG_GETARG_OID(0);
388         int64           result;
389         PgStat_StatTabEntry     *tabentry;
390
391         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
392                 result = 0;
393         else
394                 result = (int64) (tabentry->analyze_count);
395
396         PG_RETURN_INT64(result);
397 }
398
399 Datum
400 pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS)
401 {
402         Oid                     relid = PG_GETARG_OID(0);
403         int64           result;
404         PgStat_StatTabEntry     *tabentry;
405
406         if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
407                 result = 0;
408         else
409                 result = (int64) (tabentry->autovac_analyze_count);
410
411         PG_RETURN_INT64(result);
412 }
413
414 Datum
415 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
416 {
417         Oid                     funcid = PG_GETARG_OID(0);
418         PgStat_StatFuncEntry *funcentry;
419
420         if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
421                 PG_RETURN_NULL();
422         PG_RETURN_INT64(funcentry->f_numcalls);
423 }
424
425 Datum
426 pg_stat_get_function_time(PG_FUNCTION_ARGS)
427 {
428         Oid                     funcid = PG_GETARG_OID(0);
429         PgStat_StatFuncEntry *funcentry;
430
431         if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
432                 PG_RETURN_NULL();
433         PG_RETURN_INT64(funcentry->f_time);
434 }
435
436 Datum
437 pg_stat_get_function_self_time(PG_FUNCTION_ARGS)
438 {
439         Oid                     funcid = PG_GETARG_OID(0);
440         PgStat_StatFuncEntry *funcentry;
441
442         if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
443                 PG_RETURN_NULL();
444         PG_RETURN_INT64(funcentry->f_time_self);
445 }
446
447 Datum
448 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
449 {
450         FuncCallContext *funcctx;
451         int                *fctx;
452         int32           result;
453
454         /* stuff done only on the first call of the function */
455         if (SRF_IS_FIRSTCALL())
456         {
457                 /* create a function context for cross-call persistence */
458                 funcctx = SRF_FIRSTCALL_INIT();
459
460                 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
461                                                                   2 * sizeof(int));
462                 funcctx->user_fctx = fctx;
463
464                 fctx[0] = 0;
465                 fctx[1] = pgstat_fetch_stat_numbackends();
466         }
467
468         /* stuff done on every call of the function */
469         funcctx = SRF_PERCALL_SETUP();
470         fctx = funcctx->user_fctx;
471
472         fctx[0] += 1;
473         result = fctx[0];
474
475         if (result <= fctx[1])
476         {
477                 /* do when there is more left to send */
478                 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
479         }
480         else
481         {
482                 /* do when there is no more left */
483                 SRF_RETURN_DONE(funcctx);
484         }
485 }
486
487 Datum
488 pg_stat_get_activity(PG_FUNCTION_ARGS)
489 {
490         FuncCallContext *funcctx;
491
492         if (SRF_IS_FIRSTCALL())
493         {
494                 MemoryContext oldcontext;
495                 TupleDesc       tupdesc;
496
497                 funcctx = SRF_FIRSTCALL_INIT();
498
499                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
500
501                 tupdesc = CreateTemplateTupleDesc(11, false);
502                 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0);
503                 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid", INT4OID, -1, 0);
504                 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid", OIDOID, -1, 0);
505                 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name", TEXTOID, -1, 0);
506                 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "current_query", TEXTOID, -1, 0);
507                 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "waiting", BOOLOID, -1, 0);
508                 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "act_start", TIMESTAMPTZOID, -1, 0);
509                 TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start", TIMESTAMPTZOID, -1, 0);
510                 TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start", TIMESTAMPTZOID, -1, 0);
511                 TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr", INETOID, -1, 0);
512                 TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_port", INT4OID, -1, 0);
513
514                 funcctx->tuple_desc = BlessTupleDesc(tupdesc);
515
516                 funcctx->user_fctx = palloc0(sizeof(int));
517                 if (PG_ARGISNULL(0))
518                 {
519                         /* Get all backends */
520                         funcctx->max_calls = pgstat_fetch_stat_numbackends();
521                 }
522                 else
523                 {
524                         /*
525                          * Get one backend - locate by pid.
526                          *
527                          * We lookup the backend early, so we can return zero rows if it
528                          * doesn't exist, instead of returning a single row full of NULLs.
529                          */
530                         int                     pid = PG_GETARG_INT32(0);
531                         int                     i;
532                         int                     n = pgstat_fetch_stat_numbackends();
533
534                         for (i = 1; i <= n; i++)
535                         {
536                                 PgBackendStatus *be = pgstat_fetch_stat_beentry(i);
537
538                                 if (be)
539                                 {
540                                         if (be->st_procpid == pid)
541                                         {
542                                                 *(int *) (funcctx->user_fctx) = i;
543                                                 break;
544                                         }
545                                 }
546                         }
547
548                         if (*(int *) (funcctx->user_fctx) == 0)
549                                 /* Pid not found, return zero rows */
550                                 funcctx->max_calls = 0;
551                         else
552                                 funcctx->max_calls = 1;
553                 }
554
555                 MemoryContextSwitchTo(oldcontext);
556         }
557
558         /* stuff done on every call of the function */
559         funcctx = SRF_PERCALL_SETUP();
560
561         if (funcctx->call_cntr < funcctx->max_calls)
562         {
563                 /* for each row */
564                 Datum           values[11];
565                 bool            nulls[11];
566                 HeapTuple       tuple;
567                 PgBackendStatus *beentry;
568                 SockAddr        zero_clientaddr;
569
570                 MemSet(values, 0, sizeof(values));
571                 MemSet(nulls, 0, sizeof(nulls));
572
573                 if (*(int *) (funcctx->user_fctx) > 0)
574                 {
575                         /* Get specific pid slot */
576                         beentry = pgstat_fetch_stat_beentry(*(int *) (funcctx->user_fctx));
577                 }
578                 else
579                 {
580                         /* Get the next one in the list */
581                         beentry = pgstat_fetch_stat_beentry(funcctx->call_cntr + 1);            /* 1-based index */
582                 }
583                 if (!beentry)
584                 {
585                         int                     i;
586
587                         for (i = 0; i < sizeof(nulls) / sizeof(nulls[0]); i++)
588                                 nulls[i] = true;
589
590                         nulls[4] = false;
591                         values[4] = CStringGetTextDatum("<backend information not available>");
592
593                         tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
594                         SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
595                 }
596
597                 /* Values available to all callers */
598                 values[0] = ObjectIdGetDatum(beentry->st_databaseid);
599                 values[1] = Int32GetDatum(beentry->st_procpid);
600                 values[2] = ObjectIdGetDatum(beentry->st_userid);
601                 if (beentry->st_appname)
602                         values[3] = CStringGetTextDatum(beentry->st_appname);
603                 else
604                         nulls[3] = true;
605
606                 /* Values only available to same user or superuser */
607                 if (superuser() || beentry->st_userid == GetUserId())
608                 {
609                         if (*(beentry->st_activity) == '\0')
610                         {
611                                 values[4] = CStringGetTextDatum("<command string not enabled>");
612                         }
613                         else
614                         {
615                                 values[4] = CStringGetTextDatum(beentry->st_activity);
616                         }
617
618                         values[5] = BoolGetDatum(beentry->st_waiting);
619
620                         if (beentry->st_xact_start_timestamp != 0)
621                                 values[6] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
622                         else
623                                 nulls[6] = true;
624
625                         if (beentry->st_activity_start_timestamp != 0)
626                                 values[7] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
627                         else
628                                 nulls[7] = true;
629
630                         if (beentry->st_proc_start_timestamp != 0)
631                                 values[8] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
632                         else
633                                 nulls[8] = true;
634
635                         /* A zeroed client addr means we don't know */
636                         memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
637                         if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
638                                            sizeof(zero_clientaddr) == 0))
639                         {
640                                 nulls[9] = true;
641                                 nulls[10] = true;
642                         }
643                         else
644                         {
645                                 if (beentry->st_clientaddr.addr.ss_family == AF_INET
646 #ifdef HAVE_IPV6
647                                         || beentry->st_clientaddr.addr.ss_family == AF_INET6
648 #endif
649                                         )
650                                 {
651                                         char            remote_host[NI_MAXHOST];
652                                         char            remote_port[NI_MAXSERV];
653                                         int                     ret;
654
655                                         remote_host[0] = '\0';
656                                         remote_port[0] = '\0';
657                                         ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
658                                                                                          beentry->st_clientaddr.salen,
659                                                                                          remote_host, sizeof(remote_host),
660                                                                                          remote_port, sizeof(remote_port),
661                                                                                          NI_NUMERICHOST | NI_NUMERICSERV);
662                                         if (ret)
663                                         {
664                                                 nulls[9] = true;
665                                                 nulls[10] = true;
666                                         }
667                                         else
668                                         {
669                                                 clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
670                                                 values[9] = DirectFunctionCall1(inet_in,
671                                                                                            CStringGetDatum(remote_host));
672                                                 values[10] = Int32GetDatum(atoi(remote_port));
673                                         }
674                                 }
675                                 else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
676                                 {
677                                         /*
678                                          * Unix sockets always reports NULL for host and -1 for
679                                          * port, so it's possible to tell the difference to
680                                          * connections we have no permissions to view, or with
681                                          * errors.
682                                          */
683                                         nulls[9] = true;
684                                         values[10] = DatumGetInt32(-1);
685                                 }
686                                 else
687                                 {
688                                         /* Unknown address type, should never happen */
689                                         nulls[9] = true;
690                                         nulls[10] = true;
691                                 }
692                         }
693                 }
694                 else
695                 {
696                         /* No permissions to view data about this session */
697                         values[4] = CStringGetTextDatum("<insufficient privilege>");
698                         nulls[5] = true;
699                         nulls[6] = true;
700                         nulls[7] = true;
701                         nulls[8] = true;
702                         nulls[9] = true;
703                         nulls[10] = true;
704                 }
705
706                 tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
707
708                 SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
709         }
710         else
711         {
712                 /* nothing left */
713                 SRF_RETURN_DONE(funcctx);
714         }
715 }
716
717
718 Datum
719 pg_backend_pid(PG_FUNCTION_ARGS)
720 {
721         PG_RETURN_INT32(MyProcPid);
722 }
723
724
725 Datum
726 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
727 {
728         int32           beid = PG_GETARG_INT32(0);
729         PgBackendStatus *beentry;
730
731         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
732                 PG_RETURN_NULL();
733
734         PG_RETURN_INT32(beentry->st_procpid);
735 }
736
737
738 Datum
739 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
740 {
741         int32           beid = PG_GETARG_INT32(0);
742         PgBackendStatus *beentry;
743
744         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
745                 PG_RETURN_NULL();
746
747         PG_RETURN_OID(beentry->st_databaseid);
748 }
749
750
751 Datum
752 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
753 {
754         int32           beid = PG_GETARG_INT32(0);
755         PgBackendStatus *beentry;
756
757         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
758                 PG_RETURN_NULL();
759
760         PG_RETURN_OID(beentry->st_userid);
761 }
762
763
764 Datum
765 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
766 {
767         int32           beid = PG_GETARG_INT32(0);
768         PgBackendStatus *beentry;
769         const char *activity;
770
771         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
772                 activity = "<backend information not available>";
773         else if (!superuser() && beentry->st_userid != GetUserId())
774                 activity = "<insufficient privilege>";
775         else if (*(beentry->st_activity) == '\0')
776                 activity = "<command string not enabled>";
777         else
778                 activity = beentry->st_activity;
779
780         PG_RETURN_TEXT_P(cstring_to_text(activity));
781 }
782
783
784 Datum
785 pg_stat_get_backend_waiting(PG_FUNCTION_ARGS)
786 {
787         int32           beid = PG_GETARG_INT32(0);
788         bool            result;
789         PgBackendStatus *beentry;
790
791         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
792                 PG_RETURN_NULL();
793
794         if (!superuser() && beentry->st_userid != GetUserId())
795                 PG_RETURN_NULL();
796
797         result = beentry->st_waiting;
798
799         PG_RETURN_BOOL(result);
800 }
801
802
803 Datum
804 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
805 {
806         int32           beid = PG_GETARG_INT32(0);
807         TimestampTz result;
808         PgBackendStatus *beentry;
809
810         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
811                 PG_RETURN_NULL();
812
813         if (!superuser() && beentry->st_userid != GetUserId())
814                 PG_RETURN_NULL();
815
816         result = beentry->st_activity_start_timestamp;
817
818         /*
819          * No time recorded for start of current query -- this is the case if the
820          * user hasn't enabled query-level stats collection.
821          */
822         if (result == 0)
823                 PG_RETURN_NULL();
824
825         PG_RETURN_TIMESTAMPTZ(result);
826 }
827
828
829 Datum
830 pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS)
831 {
832         int32           beid = PG_GETARG_INT32(0);
833         TimestampTz result;
834         PgBackendStatus *beentry;
835
836         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
837                 PG_RETURN_NULL();
838
839         if (!superuser() && beentry->st_userid != GetUserId())
840                 PG_RETURN_NULL();
841
842         result = beentry->st_xact_start_timestamp;
843
844         if (result == 0)                        /* not in a transaction */
845                 PG_RETURN_NULL();
846
847         PG_RETURN_TIMESTAMPTZ(result);
848 }
849
850
851 Datum
852 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
853 {
854         int32           beid = PG_GETARG_INT32(0);
855         TimestampTz result;
856         PgBackendStatus *beentry;
857
858         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
859                 PG_RETURN_NULL();
860
861         if (!superuser() && beentry->st_userid != GetUserId())
862                 PG_RETURN_NULL();
863
864         result = beentry->st_proc_start_timestamp;
865
866         if (result == 0)                        /* probably can't happen? */
867                 PG_RETURN_NULL();
868
869         PG_RETURN_TIMESTAMPTZ(result);
870 }
871
872
873 Datum
874 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
875 {
876         int32           beid = PG_GETARG_INT32(0);
877         PgBackendStatus *beentry;
878         SockAddr        zero_clientaddr;
879         char            remote_host[NI_MAXHOST];
880         int                     ret;
881
882         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
883                 PG_RETURN_NULL();
884
885         if (!superuser() && beentry->st_userid != GetUserId())
886                 PG_RETURN_NULL();
887
888         /* A zeroed client addr means we don't know */
889         memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
890         if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
891                            sizeof(zero_clientaddr) == 0))
892                 PG_RETURN_NULL();
893
894         switch (beentry->st_clientaddr.addr.ss_family)
895         {
896                 case AF_INET:
897 #ifdef HAVE_IPV6
898                 case AF_INET6:
899 #endif
900                         break;
901                 default:
902                         PG_RETURN_NULL();
903         }
904
905         remote_host[0] = '\0';
906         ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
907                                                          beentry->st_clientaddr.salen,
908                                                          remote_host, sizeof(remote_host),
909                                                          NULL, 0,
910                                                          NI_NUMERICHOST | NI_NUMERICSERV);
911         if (ret)
912                 PG_RETURN_NULL();
913
914         clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
915
916         PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
917                                                                                  CStringGetDatum(remote_host)));
918 }
919
920 Datum
921 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
922 {
923         int32           beid = PG_GETARG_INT32(0);
924         PgBackendStatus *beentry;
925         SockAddr        zero_clientaddr;
926         char            remote_port[NI_MAXSERV];
927         int                     ret;
928
929         if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
930                 PG_RETURN_NULL();
931
932         if (!superuser() && beentry->st_userid != GetUserId())
933                 PG_RETURN_NULL();
934
935         /* A zeroed client addr means we don't know */
936         memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
937         if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
938                            sizeof(zero_clientaddr) == 0))
939                 PG_RETURN_NULL();
940
941         switch (beentry->st_clientaddr.addr.ss_family)
942         {
943                 case AF_INET:
944 #ifdef HAVE_IPV6
945                 case AF_INET6:
946 #endif
947                         break;
948                 case AF_UNIX:
949                         PG_RETURN_INT32(-1);
950                 default:
951                         PG_RETURN_NULL();
952         }
953
954         remote_port[0] = '\0';
955         ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
956                                                          beentry->st_clientaddr.salen,
957                                                          NULL, 0,
958                                                          remote_port, sizeof(remote_port),
959                                                          NI_NUMERICHOST | NI_NUMERICSERV);
960         if (ret)
961                 PG_RETURN_NULL();
962
963         PG_RETURN_DATUM(DirectFunctionCall1(int4in,
964                                                                                 CStringGetDatum(remote_port)));
965 }
966
967
968 Datum
969 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
970 {
971         Oid                     dbid = PG_GETARG_OID(0);
972         int32           result;
973         int                     tot_backends = pgstat_fetch_stat_numbackends();
974         int                     beid;
975
976         result = 0;
977         for (beid = 1; beid <= tot_backends; beid++)
978         {
979                 PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
980
981                 if (beentry && beentry->st_databaseid == dbid)
982                         result++;
983         }
984
985         PG_RETURN_INT32(result);
986 }
987
988
989 Datum
990 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
991 {
992         Oid                     dbid = PG_GETARG_OID(0);
993         int64           result;
994         PgStat_StatDBEntry *dbentry;
995
996         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
997                 result = 0;
998         else
999                 result = (int64) (dbentry->n_xact_commit);
1000
1001         PG_RETURN_INT64(result);
1002 }
1003
1004
1005 Datum
1006 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
1007 {
1008         Oid                     dbid = PG_GETARG_OID(0);
1009         int64           result;
1010         PgStat_StatDBEntry *dbentry;
1011
1012         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1013                 result = 0;
1014         else
1015                 result = (int64) (dbentry->n_xact_rollback);
1016
1017         PG_RETURN_INT64(result);
1018 }
1019
1020
1021 Datum
1022 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
1023 {
1024         Oid                     dbid = PG_GETARG_OID(0);
1025         int64           result;
1026         PgStat_StatDBEntry *dbentry;
1027
1028         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1029                 result = 0;
1030         else
1031                 result = (int64) (dbentry->n_blocks_fetched);
1032
1033         PG_RETURN_INT64(result);
1034 }
1035
1036
1037 Datum
1038 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
1039 {
1040         Oid                     dbid = PG_GETARG_OID(0);
1041         int64           result;
1042         PgStat_StatDBEntry *dbentry;
1043
1044         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1045                 result = 0;
1046         else
1047                 result = (int64) (dbentry->n_blocks_hit);
1048
1049         PG_RETURN_INT64(result);
1050 }
1051
1052
1053 Datum
1054 pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS)
1055 {
1056         Oid                     dbid = PG_GETARG_OID(0);
1057         int64           result;
1058         PgStat_StatDBEntry *dbentry;
1059
1060         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1061                 result = 0;
1062         else
1063                 result = (int64) (dbentry->n_tuples_returned);
1064
1065         PG_RETURN_INT64(result);
1066 }
1067
1068
1069 Datum
1070 pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS)
1071 {
1072         Oid                     dbid = PG_GETARG_OID(0);
1073         int64           result;
1074         PgStat_StatDBEntry *dbentry;
1075
1076         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1077                 result = 0;
1078         else
1079                 result = (int64) (dbentry->n_tuples_fetched);
1080
1081         PG_RETURN_INT64(result);
1082 }
1083
1084
1085 Datum
1086 pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS)
1087 {
1088         Oid                     dbid = PG_GETARG_OID(0);
1089         int64           result;
1090         PgStat_StatDBEntry *dbentry;
1091
1092         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1093                 result = 0;
1094         else
1095                 result = (int64) (dbentry->n_tuples_inserted);
1096
1097         PG_RETURN_INT64(result);
1098 }
1099
1100
1101 Datum
1102 pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS)
1103 {
1104         Oid                     dbid = PG_GETARG_OID(0);
1105         int64           result;
1106         PgStat_StatDBEntry *dbentry;
1107
1108         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1109                 result = 0;
1110         else
1111                 result = (int64) (dbentry->n_tuples_updated);
1112
1113         PG_RETURN_INT64(result);
1114 }
1115
1116
1117 Datum
1118 pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS)
1119 {
1120         Oid                     dbid = PG_GETARG_OID(0);
1121         int64           result;
1122         PgStat_StatDBEntry *dbentry;
1123
1124         if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1125                 result = 0;
1126         else
1127                 result = (int64) (dbentry->n_tuples_deleted);
1128
1129         PG_RETURN_INT64(result);
1130 }
1131
1132 Datum
1133 pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
1134 {
1135         PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints);
1136 }
1137
1138 Datum
1139 pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS)
1140 {
1141         PG_RETURN_INT64(pgstat_fetch_global()->requested_checkpoints);
1142 }
1143
1144 Datum
1145 pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS)
1146 {
1147         PG_RETURN_INT64(pgstat_fetch_global()->buf_written_checkpoints);
1148 }
1149
1150 Datum
1151 pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS)
1152 {
1153         PG_RETURN_INT64(pgstat_fetch_global()->buf_written_clean);
1154 }
1155
1156 Datum
1157 pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS)
1158 {
1159         PG_RETURN_INT64(pgstat_fetch_global()->maxwritten_clean);
1160 }
1161
1162 Datum
1163 pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS)
1164 {
1165         PG_RETURN_INT64(pgstat_fetch_global()->buf_written_backend);
1166 }
1167
1168 Datum
1169 pg_stat_get_buf_fsync_backend(PG_FUNCTION_ARGS)
1170 {
1171         PG_RETURN_INT64(pgstat_fetch_global()->buf_fsync_backend);
1172 }
1173
1174 Datum
1175 pg_stat_get_buf_alloc(PG_FUNCTION_ARGS)
1176 {
1177         PG_RETURN_INT64(pgstat_fetch_global()->buf_alloc);
1178 }
1179
1180 Datum
1181 pg_stat_get_xact_numscans(PG_FUNCTION_ARGS)
1182 {
1183         Oid                     relid = PG_GETARG_OID(0);
1184         int64           result;
1185         PgStat_TableStatus *tabentry;
1186
1187         if ((tabentry = find_tabstat_entry(relid)) == NULL)
1188                 result = 0;
1189         else
1190                 result = (int64) (tabentry->t_counts.t_numscans);
1191
1192         PG_RETURN_INT64(result);
1193 }
1194
1195 Datum
1196 pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS)
1197 {
1198         Oid                     relid = PG_GETARG_OID(0);
1199         int64           result;
1200         PgStat_TableStatus *tabentry;
1201
1202         if ((tabentry = find_tabstat_entry(relid)) == NULL)
1203                 result = 0;
1204         else
1205                 result = (int64) (tabentry->t_counts.t_tuples_returned);
1206
1207         PG_RETURN_INT64(result);
1208 }
1209
1210 Datum
1211 pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS)
1212 {
1213         Oid                     relid = PG_GETARG_OID(0);
1214         int64           result;
1215         PgStat_TableStatus *tabentry;
1216
1217         if ((tabentry = find_tabstat_entry(relid)) == NULL)
1218                 result = 0;
1219         else
1220                 result = (int64) (tabentry->t_counts.t_tuples_fetched);
1221
1222         PG_RETURN_INT64(result);
1223 }
1224
1225 Datum
1226 pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS)
1227 {
1228         Oid                     relid = PG_GETARG_OID(0);
1229         int64           result;
1230         PgStat_TableStatus *tabentry;
1231         PgStat_TableXactStatus *trans;
1232
1233         if ((tabentry = find_tabstat_entry(relid)) == NULL)
1234                 result = 0;
1235         else
1236         {
1237                 result = tabentry->t_counts.t_tuples_inserted;
1238                 /* live subtransactions' counts aren't in t_tuples_inserted yet */
1239                 for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
1240                         result += trans->tuples_inserted;
1241         }
1242
1243         PG_RETURN_INT64(result);
1244 }
1245
1246 Datum
1247 pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS)
1248 {
1249         Oid                     relid = PG_GETARG_OID(0);
1250         int64           result;
1251         PgStat_TableStatus *tabentry;
1252         PgStat_TableXactStatus *trans;
1253
1254         if ((tabentry = find_tabstat_entry(relid)) == NULL)
1255                 result = 0;
1256         else
1257         {
1258                 result = tabentry->t_counts.t_tuples_updated;
1259                 /* live subtransactions' counts aren't in t_tuples_updated yet */
1260                 for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
1261                         result += trans->tuples_updated;
1262         }
1263
1264         PG_RETURN_INT64(result);
1265 }
1266
1267 Datum
1268 pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS)
1269 {
1270         Oid                     relid = PG_GETARG_OID(0);
1271         int64           result;
1272         PgStat_TableStatus *tabentry;
1273         PgStat_TableXactStatus *trans;
1274
1275         if ((tabentry = find_tabstat_entry(relid)) == NULL)
1276                 result = 0;
1277         else
1278         {
1279                 result = tabentry->t_counts.t_tuples_deleted;
1280                 /* live subtransactions' counts aren't in t_tuples_deleted yet */
1281                 for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
1282                         result += trans->tuples_deleted;
1283         }
1284
1285         PG_RETURN_INT64(result);
1286 }
1287
1288 Datum
1289 pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS)
1290 {
1291         Oid                     relid = PG_GETARG_OID(0);
1292         int64           result;
1293         PgStat_TableStatus *tabentry;
1294
1295         if ((tabentry = find_tabstat_entry(relid)) == NULL)
1296                 result = 0;
1297         else
1298                 result = (int64) (tabentry->t_counts.t_tuples_hot_updated);
1299
1300         PG_RETURN_INT64(result);
1301 }
1302
1303 Datum
1304 pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS)
1305 {
1306         Oid                     relid = PG_GETARG_OID(0);
1307         int64           result;
1308         PgStat_TableStatus *tabentry;
1309
1310         if ((tabentry = find_tabstat_entry(relid)) == NULL)
1311                 result = 0;
1312         else
1313                 result = (int64) (tabentry->t_counts.t_blocks_fetched);
1314
1315         PG_RETURN_INT64(result);
1316 }
1317
1318 Datum
1319 pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS)
1320 {
1321         Oid                     relid = PG_GETARG_OID(0);
1322         int64           result;
1323         PgStat_TableStatus *tabentry;
1324
1325         if ((tabentry = find_tabstat_entry(relid)) == NULL)
1326                 result = 0;
1327         else
1328                 result = (int64) (tabentry->t_counts.t_blocks_hit);
1329
1330         PG_RETURN_INT64(result);
1331 }
1332
1333 Datum
1334 pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS)
1335 {
1336         Oid                     funcid = PG_GETARG_OID(0);
1337         PgStat_BackendFunctionEntry *funcentry;
1338
1339         if ((funcentry = find_funcstat_entry(funcid)) == NULL)
1340                 PG_RETURN_NULL();
1341         PG_RETURN_INT64(funcentry->f_counts.f_numcalls);
1342 }
1343
1344 Datum
1345 pg_stat_get_xact_function_time(PG_FUNCTION_ARGS)
1346 {
1347         Oid                     funcid = PG_GETARG_OID(0);
1348         PgStat_BackendFunctionEntry *funcentry;
1349
1350         if ((funcentry = find_funcstat_entry(funcid)) == NULL)
1351                 PG_RETURN_NULL();
1352         PG_RETURN_INT64(INSTR_TIME_GET_MICROSEC(funcentry->f_counts.f_time));
1353 }
1354
1355 Datum
1356 pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS)
1357 {
1358         Oid                     funcid = PG_GETARG_OID(0);
1359         PgStat_BackendFunctionEntry *funcentry;
1360
1361         if ((funcentry = find_funcstat_entry(funcid)) == NULL)
1362                 PG_RETURN_NULL();
1363         PG_RETURN_INT64(INSTR_TIME_GET_MICROSEC(funcentry->f_counts.f_time_self));
1364 }
1365
1366
1367 /* Discard the active statistics snapshot */
1368 Datum
1369 pg_stat_clear_snapshot(PG_FUNCTION_ARGS)
1370 {
1371         pgstat_clear_snapshot();
1372
1373         PG_RETURN_VOID();
1374 }
1375
1376
1377 /* Reset all counters for the current database */
1378 Datum
1379 pg_stat_reset(PG_FUNCTION_ARGS)
1380 {
1381         pgstat_reset_counters();
1382
1383         PG_RETURN_VOID();
1384 }
1385
1386 /* Reset some shared cluster-wide counters */
1387 Datum
1388 pg_stat_reset_shared(PG_FUNCTION_ARGS)
1389 {
1390         char       *target = text_to_cstring(PG_GETARG_TEXT_PP(0));
1391
1392         pgstat_reset_shared_counters(target);
1393
1394         PG_RETURN_VOID();
1395 }
1396
1397 /* Reset a a single counter in the current database */
1398 Datum
1399 pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
1400 {
1401         Oid                     taboid = PG_GETARG_OID(0);
1402
1403         pgstat_reset_single_counter(taboid, RESET_TABLE);
1404
1405         PG_RETURN_VOID();
1406 }
1407
1408 Datum
1409 pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
1410 {
1411         Oid                     funcoid = PG_GETARG_OID(0);
1412
1413         pgstat_reset_single_counter(funcoid, RESET_FUNCTION);
1414
1415         PG_RETURN_VOID();
1416 }