OSDN Git Service

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