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