1 /*-------------------------------------------------------------------------
4 * Functions for accessing the statistics collector data
6 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/utils/adt/pgstatfuncs.c
13 *-------------------------------------------------------------------------
17 #include "access/htup_details.h"
18 #include "catalog/pg_type.h"
19 #include "common/ip.h"
21 #include "miscadmin.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"
30 #define UINT32_ACCESS_ONCE(var) ((uint32)(*((volatile uint32 *)&(var))))
32 /* Global bgwriter statistics, from bgwriter.c */
33 extern PgStat_MsgBgWriter bgwriterStats;
36 pg_stat_get_numscans(PG_FUNCTION_ARGS)
38 Oid relid = PG_GETARG_OID(0);
40 PgStat_StatTabEntry *tabentry;
42 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
45 result = (int64) (tabentry->numscans);
47 PG_RETURN_INT64(result);
52 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
54 Oid relid = PG_GETARG_OID(0);
56 PgStat_StatTabEntry *tabentry;
58 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
61 result = (int64) (tabentry->tuples_returned);
63 PG_RETURN_INT64(result);
68 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
70 Oid relid = PG_GETARG_OID(0);
72 PgStat_StatTabEntry *tabentry;
74 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
77 result = (int64) (tabentry->tuples_fetched);
79 PG_RETURN_INT64(result);
84 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
86 Oid relid = PG_GETARG_OID(0);
88 PgStat_StatTabEntry *tabentry;
90 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
93 result = (int64) (tabentry->tuples_inserted);
95 PG_RETURN_INT64(result);
100 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
102 Oid relid = PG_GETARG_OID(0);
104 PgStat_StatTabEntry *tabentry;
106 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
109 result = (int64) (tabentry->tuples_updated);
111 PG_RETURN_INT64(result);
116 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
118 Oid relid = PG_GETARG_OID(0);
120 PgStat_StatTabEntry *tabentry;
122 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
125 result = (int64) (tabentry->tuples_deleted);
127 PG_RETURN_INT64(result);
132 pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
134 Oid relid = PG_GETARG_OID(0);
136 PgStat_StatTabEntry *tabentry;
138 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
141 result = (int64) (tabentry->tuples_hot_updated);
143 PG_RETURN_INT64(result);
148 pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
150 Oid relid = PG_GETARG_OID(0);
152 PgStat_StatTabEntry *tabentry;
154 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
157 result = (int64) (tabentry->n_live_tuples);
159 PG_RETURN_INT64(result);
164 pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
166 Oid relid = PG_GETARG_OID(0);
168 PgStat_StatTabEntry *tabentry;
170 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
173 result = (int64) (tabentry->n_dead_tuples);
175 PG_RETURN_INT64(result);
180 pg_stat_get_mod_since_analyze(PG_FUNCTION_ARGS)
182 Oid relid = PG_GETARG_OID(0);
184 PgStat_StatTabEntry *tabentry;
186 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
189 result = (int64) (tabentry->changes_since_analyze);
191 PG_RETURN_INT64(result);
196 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
198 Oid relid = PG_GETARG_OID(0);
200 PgStat_StatTabEntry *tabentry;
202 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
205 result = (int64) (tabentry->blocks_fetched);
207 PG_RETURN_INT64(result);
212 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
214 Oid relid = PG_GETARG_OID(0);
216 PgStat_StatTabEntry *tabentry;
218 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
221 result = (int64) (tabentry->blocks_hit);
223 PG_RETURN_INT64(result);
227 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
229 Oid relid = PG_GETARG_OID(0);
231 PgStat_StatTabEntry *tabentry;
233 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
236 result = tabentry->vacuum_timestamp;
241 PG_RETURN_TIMESTAMPTZ(result);
245 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
247 Oid relid = PG_GETARG_OID(0);
249 PgStat_StatTabEntry *tabentry;
251 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
254 result = tabentry->autovac_vacuum_timestamp;
259 PG_RETURN_TIMESTAMPTZ(result);
263 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
265 Oid relid = PG_GETARG_OID(0);
267 PgStat_StatTabEntry *tabentry;
269 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
272 result = tabentry->analyze_timestamp;
277 PG_RETURN_TIMESTAMPTZ(result);
281 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
283 Oid relid = PG_GETARG_OID(0);
285 PgStat_StatTabEntry *tabentry;
287 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
290 result = tabentry->autovac_analyze_timestamp;
295 PG_RETURN_TIMESTAMPTZ(result);
299 pg_stat_get_vacuum_count(PG_FUNCTION_ARGS)
301 Oid relid = PG_GETARG_OID(0);
303 PgStat_StatTabEntry *tabentry;
305 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
308 result = (int64) (tabentry->vacuum_count);
310 PG_RETURN_INT64(result);
314 pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS)
316 Oid relid = PG_GETARG_OID(0);
318 PgStat_StatTabEntry *tabentry;
320 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
323 result = (int64) (tabentry->autovac_vacuum_count);
325 PG_RETURN_INT64(result);
329 pg_stat_get_analyze_count(PG_FUNCTION_ARGS)
331 Oid relid = PG_GETARG_OID(0);
333 PgStat_StatTabEntry *tabentry;
335 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
338 result = (int64) (tabentry->analyze_count);
340 PG_RETURN_INT64(result);
344 pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS)
346 Oid relid = PG_GETARG_OID(0);
348 PgStat_StatTabEntry *tabentry;
350 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
353 result = (int64) (tabentry->autovac_analyze_count);
355 PG_RETURN_INT64(result);
359 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
361 Oid funcid = PG_GETARG_OID(0);
362 PgStat_StatFuncEntry *funcentry;
364 if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
366 PG_RETURN_INT64(funcentry->f_numcalls);
370 pg_stat_get_function_total_time(PG_FUNCTION_ARGS)
372 Oid funcid = PG_GETARG_OID(0);
373 PgStat_StatFuncEntry *funcentry;
375 if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
377 /* convert counter from microsec to millisec for display */
378 PG_RETURN_FLOAT8(((double) funcentry->f_total_time) / 1000.0);
382 pg_stat_get_function_self_time(PG_FUNCTION_ARGS)
384 Oid funcid = PG_GETARG_OID(0);
385 PgStat_StatFuncEntry *funcentry;
387 if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
389 /* convert counter from microsec to millisec for display */
390 PG_RETURN_FLOAT8(((double) funcentry->f_self_time) / 1000.0);
394 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
396 FuncCallContext *funcctx;
400 /* stuff done only on the first call of the function */
401 if (SRF_IS_FIRSTCALL())
403 /* create a function context for cross-call persistence */
404 funcctx = SRF_FIRSTCALL_INIT();
406 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
408 funcctx->user_fctx = fctx;
411 fctx[1] = pgstat_fetch_stat_numbackends();
414 /* stuff done on every call of the function */
415 funcctx = SRF_PERCALL_SETUP();
416 fctx = funcctx->user_fctx;
421 if (result <= fctx[1])
423 /* do when there is more left to send */
424 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
428 /* do when there is no more left */
429 SRF_RETURN_DONE(funcctx);
434 * Returns command progress information for the named command.
437 pg_stat_get_progress_info(PG_FUNCTION_ARGS)
439 #define PG_STAT_GET_PROGRESS_COLS PGSTAT_NUM_PROGRESS_PARAM + 3
440 int num_backends = pgstat_fetch_stat_numbackends();
442 char *cmd = text_to_cstring(PG_GETARG_TEXT_PP(0));
443 ProgressCommandType cmdtype;
445 Tuplestorestate *tupstore;
446 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
447 MemoryContext per_query_ctx;
448 MemoryContext oldcontext;
450 /* check to see if caller supports us returning a tuplestore */
451 if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
453 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
454 errmsg("set-valued function called in context that cannot accept a set")));
455 if (!(rsinfo->allowedModes & SFRM_Materialize))
457 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
458 errmsg("materialize mode required, but it is not " \
459 "allowed in this context")));
461 /* Build a tuple descriptor for our result type */
462 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
463 elog(ERROR, "return type must be a row type");
465 /* Translate command name into command type code. */
466 if (pg_strcasecmp(cmd, "VACUUM") == 0)
467 cmdtype = PROGRESS_COMMAND_VACUUM;
470 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
471 errmsg("invalid command name: \"%s\"", cmd)));
473 per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
474 oldcontext = MemoryContextSwitchTo(per_query_ctx);
476 tupstore = tuplestore_begin_heap(true, false, work_mem);
477 rsinfo->returnMode = SFRM_Materialize;
478 rsinfo->setResult = tupstore;
479 rsinfo->setDesc = tupdesc;
480 MemoryContextSwitchTo(oldcontext);
483 for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
485 LocalPgBackendStatus *local_beentry;
486 PgBackendStatus *beentry;
487 Datum values[PG_STAT_GET_PROGRESS_COLS];
488 bool nulls[PG_STAT_GET_PROGRESS_COLS];
491 MemSet(values, 0, sizeof(values));
492 MemSet(nulls, 0, sizeof(nulls));
494 local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
499 beentry = &local_beentry->backendStatus;
502 * Report values for only those backends which are running the given
505 if (!beentry || beentry->st_progress_command != cmdtype)
508 /* Value available to all callers */
509 values[0] = Int32GetDatum(beentry->st_procpid);
510 values[1] = ObjectIdGetDatum(beentry->st_databaseid);
512 /* show rest of the values including relid only to role members */
513 if (has_privs_of_role(GetUserId(), beentry->st_userid))
515 values[2] = ObjectIdGetDatum(beentry->st_progress_command_target);
516 for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++)
517 values[i + 3] = Int64GetDatum(beentry->st_progress_param[i]);
522 for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++)
526 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
529 /* clean up and return the tuplestore */
530 tuplestore_donestoring(tupstore);
536 * Returns activity of PG backends.
539 pg_stat_get_activity(PG_FUNCTION_ARGS)
541 #define PG_STAT_GET_ACTIVITY_COLS 23
542 int num_backends = pgstat_fetch_stat_numbackends();
544 int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
545 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
547 Tuplestorestate *tupstore;
548 MemoryContext per_query_ctx;
549 MemoryContext oldcontext;
551 /* check to see if caller supports us returning a tuplestore */
552 if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
554 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
555 errmsg("set-valued function called in context that cannot accept a set")));
556 if (!(rsinfo->allowedModes & SFRM_Materialize))
558 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
559 errmsg("materialize mode required, but it is not " \
560 "allowed in this context")));
562 /* Build a tuple descriptor for our result type */
563 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
564 elog(ERROR, "return type must be a row type");
566 per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
567 oldcontext = MemoryContextSwitchTo(per_query_ctx);
569 tupstore = tuplestore_begin_heap(true, false, work_mem);
570 rsinfo->returnMode = SFRM_Materialize;
571 rsinfo->setResult = tupstore;
572 rsinfo->setDesc = tupdesc;
574 MemoryContextSwitchTo(oldcontext);
577 for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
580 Datum values[PG_STAT_GET_ACTIVITY_COLS];
581 bool nulls[PG_STAT_GET_ACTIVITY_COLS];
582 LocalPgBackendStatus *local_beentry;
583 PgBackendStatus *beentry;
585 const char *wait_event_type;
586 const char *wait_event;
588 MemSet(values, 0, sizeof(values));
589 MemSet(nulls, 0, sizeof(nulls));
591 /* Get the next one in the list */
592 local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
597 /* Ignore missing entries if looking for specific PID */
601 for (i = 0; i < lengthof(nulls); i++)
605 values[5] = CStringGetTextDatum("<backend information not available>");
607 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
611 beentry = &local_beentry->backendStatus;
613 /* If looking for specific PID, ignore all the others */
614 if (pid != -1 && beentry->st_procpid != pid)
617 /* Values available to all callers */
618 values[0] = ObjectIdGetDatum(beentry->st_databaseid);
619 values[1] = Int32GetDatum(beentry->st_procpid);
620 values[2] = ObjectIdGetDatum(beentry->st_userid);
621 if (beentry->st_appname)
622 values[3] = CStringGetTextDatum(beentry->st_appname);
626 if (TransactionIdIsValid(local_beentry->backend_xid))
627 values[15] = TransactionIdGetDatum(local_beentry->backend_xid);
631 if (TransactionIdIsValid(local_beentry->backend_xmin))
632 values[16] = TransactionIdGetDatum(local_beentry->backend_xmin);
638 values[17] = BoolGetDatum(true); /* ssl */
639 values[18] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
640 values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
641 values[20] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
642 values[21] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
643 values[22] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn);
647 values[17] = BoolGetDatum(false); /* ssl */
648 nulls[18] = nulls[19] = nulls[20] = nulls[21] = nulls[22] = true;
651 /* Values only available to role member */
652 if (has_privs_of_role(GetUserId(), beentry->st_userid))
654 SockAddr zero_clientaddr;
656 switch (beentry->st_state)
659 values[4] = CStringGetTextDatum("idle");
662 values[4] = CStringGetTextDatum("active");
664 case STATE_IDLEINTRANSACTION:
665 values[4] = CStringGetTextDatum("idle in transaction");
668 values[4] = CStringGetTextDatum("fastpath function call");
670 case STATE_IDLEINTRANSACTION_ABORTED:
671 values[4] = CStringGetTextDatum("idle in transaction (aborted)");
674 values[4] = CStringGetTextDatum("disabled");
676 case STATE_UNDEFINED:
681 values[5] = CStringGetTextDatum(beentry->st_activity);
683 proc = BackendPidGetProc(beentry->st_procpid);
686 uint32 raw_wait_event;
688 raw_wait_event = UINT32_ACCESS_ONCE(proc->wait_event_info);
689 wait_event_type = pgstat_get_wait_event_type(raw_wait_event);
690 wait_event = pgstat_get_wait_event(raw_wait_event);
695 wait_event_type = NULL;
700 values[6] = CStringGetTextDatum(wait_event_type);
705 values[7] = CStringGetTextDatum(wait_event);
709 if (beentry->st_xact_start_timestamp != 0)
710 values[8] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
714 if (beentry->st_activity_start_timestamp != 0)
715 values[9] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
719 if (beentry->st_proc_start_timestamp != 0)
720 values[10] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
724 if (beentry->st_state_start_timestamp != 0)
725 values[11] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
729 /* A zeroed client addr means we don't know */
730 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
731 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
732 sizeof(zero_clientaddr)) == 0)
740 if (beentry->st_clientaddr.addr.ss_family == AF_INET
742 || beentry->st_clientaddr.addr.ss_family == AF_INET6
746 char remote_host[NI_MAXHOST];
747 char remote_port[NI_MAXSERV];
750 remote_host[0] = '\0';
751 remote_port[0] = '\0';
752 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
753 beentry->st_clientaddr.salen,
754 remote_host, sizeof(remote_host),
755 remote_port, sizeof(remote_port),
756 NI_NUMERICHOST | NI_NUMERICSERV);
759 clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
760 values[12] = DirectFunctionCall1(inet_in,
761 CStringGetDatum(remote_host));
762 if (beentry->st_clienthostname &&
763 beentry->st_clienthostname[0])
764 values[13] = CStringGetTextDatum(beentry->st_clienthostname);
767 values[14] = Int32GetDatum(atoi(remote_port));
776 else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
779 * Unix sockets always reports NULL for host and -1 for
780 * port, so it's possible to tell the difference to
781 * connections we have no permissions to view, or with
786 values[14] = DatumGetInt32(-1);
790 /* Unknown address type, should never happen */
799 /* No permissions to view data about this session */
800 values[5] = CStringGetTextDatum("<insufficient privilege>");
813 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
815 /* If only a single backend was requested, and we found it, break. */
820 /* clean up and return the tuplestore */
821 tuplestore_donestoring(tupstore);
828 pg_backend_pid(PG_FUNCTION_ARGS)
830 PG_RETURN_INT32(MyProcPid);
835 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
837 int32 beid = PG_GETARG_INT32(0);
838 PgBackendStatus *beentry;
840 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
843 PG_RETURN_INT32(beentry->st_procpid);
848 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
850 int32 beid = PG_GETARG_INT32(0);
851 PgBackendStatus *beentry;
853 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
856 PG_RETURN_OID(beentry->st_databaseid);
861 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
863 int32 beid = PG_GETARG_INT32(0);
864 PgBackendStatus *beentry;
866 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
869 PG_RETURN_OID(beentry->st_userid);
874 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
876 int32 beid = PG_GETARG_INT32(0);
877 PgBackendStatus *beentry;
878 const char *activity;
880 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
881 activity = "<backend information not available>";
882 else if (!has_privs_of_role(GetUserId(), beentry->st_userid))
883 activity = "<insufficient privilege>";
884 else if (*(beentry->st_activity) == '\0')
885 activity = "<command string not enabled>";
887 activity = beentry->st_activity;
889 PG_RETURN_TEXT_P(cstring_to_text(activity));
893 pg_stat_get_backend_wait_event_type(PG_FUNCTION_ARGS)
895 int32 beid = PG_GETARG_INT32(0);
896 PgBackendStatus *beentry;
898 const char *wait_event_type = NULL;
900 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
901 wait_event_type = "<backend information not available>";
902 else if (!has_privs_of_role(GetUserId(), beentry->st_userid))
903 wait_event_type = "<insufficient privilege>";
904 else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL)
905 wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info);
907 if (!wait_event_type)
910 PG_RETURN_TEXT_P(cstring_to_text(wait_event_type));
914 pg_stat_get_backend_wait_event(PG_FUNCTION_ARGS)
916 int32 beid = PG_GETARG_INT32(0);
917 PgBackendStatus *beentry;
919 const char *wait_event = NULL;
921 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
922 wait_event = "<backend information not available>";
923 else if (!has_privs_of_role(GetUserId(), beentry->st_userid))
924 wait_event = "<insufficient privilege>";
925 else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL)
926 wait_event = pgstat_get_wait_event(proc->wait_event_info);
931 PG_RETURN_TEXT_P(cstring_to_text(wait_event));
936 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
938 int32 beid = PG_GETARG_INT32(0);
940 PgBackendStatus *beentry;
942 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
945 if (!has_privs_of_role(GetUserId(), beentry->st_userid))
948 result = beentry->st_activity_start_timestamp;
951 * No time recorded for start of current query -- this is the case if the
952 * user hasn't enabled query-level stats collection.
957 PG_RETURN_TIMESTAMPTZ(result);
962 pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS)
964 int32 beid = PG_GETARG_INT32(0);
966 PgBackendStatus *beentry;
968 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
971 if (!has_privs_of_role(GetUserId(), beentry->st_userid))
974 result = beentry->st_xact_start_timestamp;
976 if (result == 0) /* not in a transaction */
979 PG_RETURN_TIMESTAMPTZ(result);
984 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
986 int32 beid = PG_GETARG_INT32(0);
988 PgBackendStatus *beentry;
990 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
993 if (!has_privs_of_role(GetUserId(), beentry->st_userid))
996 result = beentry->st_proc_start_timestamp;
998 if (result == 0) /* probably can't happen? */
1001 PG_RETURN_TIMESTAMPTZ(result);
1006 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
1008 int32 beid = PG_GETARG_INT32(0);
1009 PgBackendStatus *beentry;
1010 SockAddr zero_clientaddr;
1011 char remote_host[NI_MAXHOST];
1014 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
1017 if (!has_privs_of_role(GetUserId(), beentry->st_userid))
1020 /* A zeroed client addr means we don't know */
1021 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
1022 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
1023 sizeof(zero_clientaddr)) == 0)
1026 switch (beentry->st_clientaddr.addr.ss_family)
1037 remote_host[0] = '\0';
1038 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
1039 beentry->st_clientaddr.salen,
1040 remote_host, sizeof(remote_host),
1042 NI_NUMERICHOST | NI_NUMERICSERV);
1046 clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
1048 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
1049 CStringGetDatum(remote_host)));
1053 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
1055 int32 beid = PG_GETARG_INT32(0);
1056 PgBackendStatus *beentry;
1057 SockAddr zero_clientaddr;
1058 char remote_port[NI_MAXSERV];
1061 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
1064 if (!has_privs_of_role(GetUserId(), beentry->st_userid))
1067 /* A zeroed client addr means we don't know */
1068 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
1069 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
1070 sizeof(zero_clientaddr)) == 0)
1073 switch (beentry->st_clientaddr.addr.ss_family)
1081 PG_RETURN_INT32(-1);
1086 remote_port[0] = '\0';
1087 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
1088 beentry->st_clientaddr.salen,
1090 remote_port, sizeof(remote_port),
1091 NI_NUMERICHOST | NI_NUMERICSERV);
1095 PG_RETURN_DATUM(DirectFunctionCall1(int4in,
1096 CStringGetDatum(remote_port)));
1101 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
1103 Oid dbid = PG_GETARG_OID(0);
1105 int tot_backends = pgstat_fetch_stat_numbackends();
1109 for (beid = 1; beid <= tot_backends; beid++)
1111 PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
1113 if (beentry && beentry->st_databaseid == dbid)
1117 PG_RETURN_INT32(result);
1122 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
1124 Oid dbid = PG_GETARG_OID(0);
1126 PgStat_StatDBEntry *dbentry;
1128 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1131 result = (int64) (dbentry->n_xact_commit);
1133 PG_RETURN_INT64(result);
1138 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
1140 Oid dbid = PG_GETARG_OID(0);
1142 PgStat_StatDBEntry *dbentry;
1144 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1147 result = (int64) (dbentry->n_xact_rollback);
1149 PG_RETURN_INT64(result);
1154 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
1156 Oid dbid = PG_GETARG_OID(0);
1158 PgStat_StatDBEntry *dbentry;
1160 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1163 result = (int64) (dbentry->n_blocks_fetched);
1165 PG_RETURN_INT64(result);
1170 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
1172 Oid dbid = PG_GETARG_OID(0);
1174 PgStat_StatDBEntry *dbentry;
1176 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1179 result = (int64) (dbentry->n_blocks_hit);
1181 PG_RETURN_INT64(result);
1186 pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS)
1188 Oid dbid = PG_GETARG_OID(0);
1190 PgStat_StatDBEntry *dbentry;
1192 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1195 result = (int64) (dbentry->n_tuples_returned);
1197 PG_RETURN_INT64(result);
1202 pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS)
1204 Oid dbid = PG_GETARG_OID(0);
1206 PgStat_StatDBEntry *dbentry;
1208 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1211 result = (int64) (dbentry->n_tuples_fetched);
1213 PG_RETURN_INT64(result);
1218 pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS)
1220 Oid dbid = PG_GETARG_OID(0);
1222 PgStat_StatDBEntry *dbentry;
1224 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1227 result = (int64) (dbentry->n_tuples_inserted);
1229 PG_RETURN_INT64(result);
1234 pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS)
1236 Oid dbid = PG_GETARG_OID(0);
1238 PgStat_StatDBEntry *dbentry;
1240 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1243 result = (int64) (dbentry->n_tuples_updated);
1245 PG_RETURN_INT64(result);
1250 pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS)
1252 Oid dbid = PG_GETARG_OID(0);
1254 PgStat_StatDBEntry *dbentry;
1256 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1259 result = (int64) (dbentry->n_tuples_deleted);
1261 PG_RETURN_INT64(result);
1265 pg_stat_get_db_stat_reset_time(PG_FUNCTION_ARGS)
1267 Oid dbid = PG_GETARG_OID(0);
1269 PgStat_StatDBEntry *dbentry;
1271 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1274 result = dbentry->stat_reset_timestamp;
1279 PG_RETURN_TIMESTAMPTZ(result);
1283 pg_stat_get_db_temp_files(PG_FUNCTION_ARGS)
1285 Oid dbid = PG_GETARG_OID(0);
1287 PgStat_StatDBEntry *dbentry;
1289 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1292 result = dbentry->n_temp_files;
1294 PG_RETURN_INT64(result);
1299 pg_stat_get_db_temp_bytes(PG_FUNCTION_ARGS)
1301 Oid dbid = PG_GETARG_OID(0);
1303 PgStat_StatDBEntry *dbentry;
1305 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1308 result = dbentry->n_temp_bytes;
1310 PG_RETURN_INT64(result);
1314 pg_stat_get_db_conflict_tablespace(PG_FUNCTION_ARGS)
1316 Oid dbid = PG_GETARG_OID(0);
1318 PgStat_StatDBEntry *dbentry;
1320 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1323 result = (int64) (dbentry->n_conflict_tablespace);
1325 PG_RETURN_INT64(result);
1329 pg_stat_get_db_conflict_lock(PG_FUNCTION_ARGS)
1331 Oid dbid = PG_GETARG_OID(0);
1333 PgStat_StatDBEntry *dbentry;
1335 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1338 result = (int64) (dbentry->n_conflict_lock);
1340 PG_RETURN_INT64(result);
1344 pg_stat_get_db_conflict_snapshot(PG_FUNCTION_ARGS)
1346 Oid dbid = PG_GETARG_OID(0);
1348 PgStat_StatDBEntry *dbentry;
1350 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1353 result = (int64) (dbentry->n_conflict_snapshot);
1355 PG_RETURN_INT64(result);
1359 pg_stat_get_db_conflict_bufferpin(PG_FUNCTION_ARGS)
1361 Oid dbid = PG_GETARG_OID(0);
1363 PgStat_StatDBEntry *dbentry;
1365 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1368 result = (int64) (dbentry->n_conflict_bufferpin);
1370 PG_RETURN_INT64(result);
1374 pg_stat_get_db_conflict_startup_deadlock(PG_FUNCTION_ARGS)
1376 Oid dbid = PG_GETARG_OID(0);
1378 PgStat_StatDBEntry *dbentry;
1380 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1383 result = (int64) (dbentry->n_conflict_startup_deadlock);
1385 PG_RETURN_INT64(result);
1389 pg_stat_get_db_conflict_all(PG_FUNCTION_ARGS)
1391 Oid dbid = PG_GETARG_OID(0);
1393 PgStat_StatDBEntry *dbentry;
1395 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1399 dbentry->n_conflict_tablespace +
1400 dbentry->n_conflict_lock +
1401 dbentry->n_conflict_snapshot +
1402 dbentry->n_conflict_bufferpin +
1403 dbentry->n_conflict_startup_deadlock);
1405 PG_RETURN_INT64(result);
1409 pg_stat_get_db_deadlocks(PG_FUNCTION_ARGS)
1411 Oid dbid = PG_GETARG_OID(0);
1413 PgStat_StatDBEntry *dbentry;
1415 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1418 result = (int64) (dbentry->n_deadlocks);
1420 PG_RETURN_INT64(result);
1424 pg_stat_get_db_blk_read_time(PG_FUNCTION_ARGS)
1426 Oid dbid = PG_GETARG_OID(0);
1428 PgStat_StatDBEntry *dbentry;
1430 /* convert counter from microsec to millisec for display */
1431 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1434 result = ((double) dbentry->n_block_read_time) / 1000.0;
1436 PG_RETURN_FLOAT8(result);
1440 pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS)
1442 Oid dbid = PG_GETARG_OID(0);
1444 PgStat_StatDBEntry *dbentry;
1446 /* convert counter from microsec to millisec for display */
1447 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
1450 result = ((double) dbentry->n_block_write_time) / 1000.0;
1452 PG_RETURN_FLOAT8(result);
1456 pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
1458 PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints);
1462 pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS)
1464 PG_RETURN_INT64(pgstat_fetch_global()->requested_checkpoints);
1468 pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS)
1470 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_checkpoints);
1474 pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS)
1476 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_clean);
1480 pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS)
1482 PG_RETURN_INT64(pgstat_fetch_global()->maxwritten_clean);
1486 pg_stat_get_checkpoint_write_time(PG_FUNCTION_ARGS)
1488 /* time is already in msec, just convert to double for presentation */
1489 PG_RETURN_FLOAT8((double) pgstat_fetch_global()->checkpoint_write_time);
1493 pg_stat_get_checkpoint_sync_time(PG_FUNCTION_ARGS)
1495 /* time is already in msec, just convert to double for presentation */
1496 PG_RETURN_FLOAT8((double) pgstat_fetch_global()->checkpoint_sync_time);
1500 pg_stat_get_bgwriter_stat_reset_time(PG_FUNCTION_ARGS)
1502 PG_RETURN_TIMESTAMPTZ(pgstat_fetch_global()->stat_reset_timestamp);
1506 pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS)
1508 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_backend);
1512 pg_stat_get_buf_fsync_backend(PG_FUNCTION_ARGS)
1514 PG_RETURN_INT64(pgstat_fetch_global()->buf_fsync_backend);
1518 pg_stat_get_buf_alloc(PG_FUNCTION_ARGS)
1520 PG_RETURN_INT64(pgstat_fetch_global()->buf_alloc);
1524 pg_stat_get_xact_numscans(PG_FUNCTION_ARGS)
1526 Oid relid = PG_GETARG_OID(0);
1528 PgStat_TableStatus *tabentry;
1530 if ((tabentry = find_tabstat_entry(relid)) == NULL)
1533 result = (int64) (tabentry->t_counts.t_numscans);
1535 PG_RETURN_INT64(result);
1539 pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS)
1541 Oid relid = PG_GETARG_OID(0);
1543 PgStat_TableStatus *tabentry;
1545 if ((tabentry = find_tabstat_entry(relid)) == NULL)
1548 result = (int64) (tabentry->t_counts.t_tuples_returned);
1550 PG_RETURN_INT64(result);
1554 pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS)
1556 Oid relid = PG_GETARG_OID(0);
1558 PgStat_TableStatus *tabentry;
1560 if ((tabentry = find_tabstat_entry(relid)) == NULL)
1563 result = (int64) (tabentry->t_counts.t_tuples_fetched);
1565 PG_RETURN_INT64(result);
1569 pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS)
1571 Oid relid = PG_GETARG_OID(0);
1573 PgStat_TableStatus *tabentry;
1574 PgStat_TableXactStatus *trans;
1576 if ((tabentry = find_tabstat_entry(relid)) == NULL)
1580 result = tabentry->t_counts.t_tuples_inserted;
1581 /* live subtransactions' counts aren't in t_tuples_inserted yet */
1582 for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
1583 result += trans->tuples_inserted;
1586 PG_RETURN_INT64(result);
1590 pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS)
1592 Oid relid = PG_GETARG_OID(0);
1594 PgStat_TableStatus *tabentry;
1595 PgStat_TableXactStatus *trans;
1597 if ((tabentry = find_tabstat_entry(relid)) == NULL)
1601 result = tabentry->t_counts.t_tuples_updated;
1602 /* live subtransactions' counts aren't in t_tuples_updated yet */
1603 for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
1604 result += trans->tuples_updated;
1607 PG_RETURN_INT64(result);
1611 pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS)
1613 Oid relid = PG_GETARG_OID(0);
1615 PgStat_TableStatus *tabentry;
1616 PgStat_TableXactStatus *trans;
1618 if ((tabentry = find_tabstat_entry(relid)) == NULL)
1622 result = tabentry->t_counts.t_tuples_deleted;
1623 /* live subtransactions' counts aren't in t_tuples_deleted yet */
1624 for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
1625 result += trans->tuples_deleted;
1628 PG_RETURN_INT64(result);
1632 pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS)
1634 Oid relid = PG_GETARG_OID(0);
1636 PgStat_TableStatus *tabentry;
1638 if ((tabentry = find_tabstat_entry(relid)) == NULL)
1641 result = (int64) (tabentry->t_counts.t_tuples_hot_updated);
1643 PG_RETURN_INT64(result);
1647 pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS)
1649 Oid relid = PG_GETARG_OID(0);
1651 PgStat_TableStatus *tabentry;
1653 if ((tabentry = find_tabstat_entry(relid)) == NULL)
1656 result = (int64) (tabentry->t_counts.t_blocks_fetched);
1658 PG_RETURN_INT64(result);
1662 pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS)
1664 Oid relid = PG_GETARG_OID(0);
1666 PgStat_TableStatus *tabentry;
1668 if ((tabentry = find_tabstat_entry(relid)) == NULL)
1671 result = (int64) (tabentry->t_counts.t_blocks_hit);
1673 PG_RETURN_INT64(result);
1677 pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS)
1679 Oid funcid = PG_GETARG_OID(0);
1680 PgStat_BackendFunctionEntry *funcentry;
1682 if ((funcentry = find_funcstat_entry(funcid)) == NULL)
1684 PG_RETURN_INT64(funcentry->f_counts.f_numcalls);
1688 pg_stat_get_xact_function_total_time(PG_FUNCTION_ARGS)
1690 Oid funcid = PG_GETARG_OID(0);
1691 PgStat_BackendFunctionEntry *funcentry;
1693 if ((funcentry = find_funcstat_entry(funcid)) == NULL)
1695 PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_total_time));
1699 pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS)
1701 Oid funcid = PG_GETARG_OID(0);
1702 PgStat_BackendFunctionEntry *funcentry;
1704 if ((funcentry = find_funcstat_entry(funcid)) == NULL)
1706 PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_self_time));
1710 /* Get the timestamp of the current statistics snapshot */
1712 pg_stat_get_snapshot_timestamp(PG_FUNCTION_ARGS)
1714 PG_RETURN_TIMESTAMPTZ(pgstat_fetch_global()->stats_timestamp);
1717 /* Discard the active statistics snapshot */
1719 pg_stat_clear_snapshot(PG_FUNCTION_ARGS)
1721 pgstat_clear_snapshot();
1727 /* Reset all counters for the current database */
1729 pg_stat_reset(PG_FUNCTION_ARGS)
1731 pgstat_reset_counters();
1736 /* Reset some shared cluster-wide counters */
1738 pg_stat_reset_shared(PG_FUNCTION_ARGS)
1740 char *target = text_to_cstring(PG_GETARG_TEXT_PP(0));
1742 pgstat_reset_shared_counters(target);
1747 /* Reset a single counter in the current database */
1749 pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
1751 Oid taboid = PG_GETARG_OID(0);
1753 pgstat_reset_single_counter(taboid, RESET_TABLE);
1759 pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
1761 Oid funcoid = PG_GETARG_OID(0);
1763 pgstat_reset_single_counter(funcoid, RESET_FUNCTION);
1769 pg_stat_get_archiver(PG_FUNCTION_ARGS)
1774 PgStat_ArchiverStats *archiver_stats;
1776 /* Initialise values and NULL flags arrays */
1777 MemSet(values, 0, sizeof(values));
1778 MemSet(nulls, 0, sizeof(nulls));
1780 /* Initialise attributes information in the tuple descriptor */
1781 tupdesc = CreateTemplateTupleDesc(7, false);
1782 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "archived_count",
1784 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "last_archived_wal",
1786 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "last_archived_time",
1787 TIMESTAMPTZOID, -1, 0);
1788 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "failed_count",
1790 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "last_failed_wal",
1792 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "last_failed_time",
1793 TIMESTAMPTZOID, -1, 0);
1794 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stats_reset",
1795 TIMESTAMPTZOID, -1, 0);
1797 BlessTupleDesc(tupdesc);
1799 /* Get statistics about the archiver process */
1800 archiver_stats = pgstat_fetch_stat_archiver();
1802 /* Fill values and NULLs */
1803 values[0] = Int64GetDatum(archiver_stats->archived_count);
1804 if (*(archiver_stats->last_archived_wal) == '\0')
1807 values[1] = CStringGetTextDatum(archiver_stats->last_archived_wal);
1809 if (archiver_stats->last_archived_timestamp == 0)
1812 values[2] = TimestampTzGetDatum(archiver_stats->last_archived_timestamp);
1814 values[3] = Int64GetDatum(archiver_stats->failed_count);
1815 if (*(archiver_stats->last_failed_wal) == '\0')
1818 values[4] = CStringGetTextDatum(archiver_stats->last_failed_wal);
1820 if (archiver_stats->last_failed_timestamp == 0)
1823 values[5] = TimestampTzGetDatum(archiver_stats->last_failed_timestamp);
1825 if (archiver_stats->stat_reset_timestamp == 0)
1828 values[6] = TimestampTzGetDatum(archiver_stats->stat_reset_timestamp);
1830 /* Returns the record as Datum */
1831 PG_RETURN_DATUM(HeapTupleGetDatum(
1832 heap_form_tuple(tupdesc, values, nulls)));