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