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