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