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