Skip to content

Commit 0423de4

Browse files
committed
Make the pg_stat_activity view call a SRF (pg_stat_get_activity())
instead of calling a bunch of individual functions. This function can also be called directly, taking a PID as an argument, to return only the data for a single PID.
1 parent 8008988 commit 0423de4

File tree

6 files changed

+270
-30
lines changed

6 files changed

+270
-30
lines changed

doc/src/sgml/monitoring.sgml

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.57 2008/04/10 13:34:33 alvherre Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.58 2008/05/07 14:41:55 mha Exp $ -->
22

33
<chapter id="monitoring">
44
<title>Monitoring Database Activity</title>
@@ -655,20 +655,31 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
655655
</row>
656656

657657
<row>
658-
<entry><literal><function>pg_stat_get_backend_idset</function>()</literal></entry>
659-
<entry><type>setof integer</type></entry>
658+
<!-- See also the entry for this in func.sgml -->
659+
<entry><literal><function>pg_backend_pid</function>()</literal></entry>
660+
<entry><type>integer</type></entry>
660661
<entry>
661-
Set of currently active server process numbers (from 1 to the
662-
number of active server processes). See usage example in the text
662+
Process ID of the server process attached to the current session
663663
</entry>
664664
</row>
665665

666666
<row>
667-
<!-- See also the entry for this in func.sgml -->
668-
<entry><literal><function>pg_backend_pid</function>()</literal></entry>
669-
<entry><type>integer</type></entry>
667+
<entry><literal><function>pg_stat_get_activity</function>(<type>integer</type>)</literal></entry>
668+
<entry><type>setof record</type></entry>
670669
<entry>
671-
Process ID of the server process attached to the current session
670+
Returns a record of information about the backend with the specified pid, or
671+
one record for each active backend in the system if <symbol>NULL</symbol> is
672+
specified. The fields returned are the same as in the
673+
<structname>pg_stat_activity</structname> view
674+
</entry>
675+
</row>
676+
677+
<row>
678+
<entry><literal><function>pg_stat_get_backend_idset</function>()</literal></entry>
679+
<entry><type>setof integer</type></entry>
680+
<entry>
681+
Set of currently active server process numbers (from 1 to the
682+
number of active server processes). See usage example in the text
672683
</entry>
673684
</row>
674685

@@ -869,6 +880,8 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
869880
</note>
870881

871882
<para>
883+
All functions to access information about backends are indexed by backend id
884+
number, except <function>pg_stat_get_activity</function> which is indexed by PID.
872885
The function <function>pg_stat_get_backend_idset</function> provides
873886
a convenient way to generate one row for each active server process. For
874887
example, to show the <acronym>PID</>s and current queries of all server processes:

src/backend/catalog/system_views.sql

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 1996-2008, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.49 2008/03/10 12:55:13 mha Exp $
6+
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.50 2008/05/07 14:41:55 mha Exp $
77
*/
88

99
CREATE VIEW pg_roles AS
@@ -341,23 +341,26 @@ CREATE VIEW pg_statio_user_sequences AS
341341

342342
CREATE VIEW pg_stat_activity AS
343343
SELECT
344-
D.oid AS datid,
345-
D.datname AS datname,
346-
pg_stat_get_backend_pid(S.backendid) AS procpid,
347-
pg_stat_get_backend_userid(S.backendid) AS usesysid,
348-
U.rolname AS usename,
349-
pg_stat_get_backend_activity(S.backendid) AS current_query,
350-
pg_stat_get_backend_waiting(S.backendid) AS waiting,
351-
pg_stat_get_backend_xact_start(S.backendid) AS xact_start,
352-
pg_stat_get_backend_activity_start(S.backendid) AS query_start,
353-
pg_stat_get_backend_start(S.backendid) AS backend_start,
354-
pg_stat_get_backend_client_addr(S.backendid) AS client_addr,
355-
pg_stat_get_backend_client_port(S.backendid) AS client_port
344+
S.datid AS datid,
345+
D.datname AS datname,
346+
S.procpid,
347+
S.usesysid,
348+
U.rolname AS usename,
349+
S.current_query,
350+
S.waiting,
351+
S.xact_start,
352+
S.query_start,
353+
S.backend_start,
354+
S.client_addr,
355+
S.client_port
356356
FROM pg_database D,
357-
(SELECT pg_stat_get_backend_idset() AS backendid) AS S,
357+
pg_stat_get_activity(NULL) AS S(datid oid, procpid int,
358+
usesysid oid, current_query text, waiting boolean,
359+
xact_start timestamptz, query_start timestamptz,
360+
backend_start timestamptz, client_addr inet, client_port int),
358361
pg_authid U
359-
WHERE pg_stat_get_backend_dbid(S.backendid) = D.oid AND
360-
pg_stat_get_backend_userid(S.backendid) = U.oid;
362+
WHERE S.datid = D.oid AND
363+
S.usesysid = U.oid;
361364

362365
CREATE VIEW pg_stat_database AS
363366
SELECT

src/backend/utils/adt/pgstatfuncs.c

Lines changed: 223 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.49 2008/03/25 22:42:44 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.50 2008/05/07 14:41:55 mha Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -17,6 +17,8 @@
1717
#include "funcapi.h"
1818
#include "miscadmin.h"
1919
#include "pgstat.h"
20+
#include "catalog/pg_type.h"
21+
#include "access/heapam.h"
2022
#include "utils/builtins.h"
2123
#include "utils/inet.h"
2224
#include "libpq/ip.h"
@@ -39,6 +41,7 @@ extern Datum pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS);
3941
extern Datum pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS);
4042

4143
extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
44+
extern Datum pg_stat_get_activity(PG_FUNCTION_ARGS);
4245
extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
4346
extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
4447
extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
@@ -363,6 +366,225 @@ pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
363366
}
364367
}
365368

369+
Datum
370+
pg_stat_get_activity(PG_FUNCTION_ARGS)
371+
{
372+
FuncCallContext *funcctx;
373+
374+
if (SRF_IS_FIRSTCALL())
375+
{
376+
MemoryContext oldcontext;
377+
TupleDesc tupdesc;
378+
379+
funcctx = SRF_FIRSTCALL_INIT();
380+
381+
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
382+
383+
tupdesc = CreateTemplateTupleDesc(10, false);
384+
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0);
385+
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid", INT4OID, -1, 0);
386+
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid", OIDOID, -1, 0);
387+
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "current_query", TEXTOID, -1, 0);
388+
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "waiting", BOOLOID, -1, 0);
389+
TupleDescInitEntry(tupdesc, (AttrNumber) 6, "act_start", TIMESTAMPTZOID, -1, 0);
390+
TupleDescInitEntry(tupdesc, (AttrNumber) 7, "query_start", TIMESTAMPTZOID, -1, 0);
391+
TupleDescInitEntry(tupdesc, (AttrNumber) 8, "backend_start", TIMESTAMPTZOID, -1, 0);
392+
TupleDescInitEntry(tupdesc, (AttrNumber) 9, "client_addr", INETOID, -1, 0);
393+
TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_port", INT4OID, -1, 0);
394+
395+
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
396+
397+
funcctx->user_fctx = palloc0(sizeof(int));
398+
if (PG_ARGISNULL(0))
399+
{
400+
/* Get all backends */
401+
funcctx->max_calls = pgstat_fetch_stat_numbackends();
402+
}
403+
else
404+
{
405+
/*
406+
* Get one backend - locate by pid.
407+
*
408+
* We lookup the backend early, so we can return zero rows if it doesn't
409+
* exist, instead of returning a single row full of NULLs.
410+
*/
411+
int pid = PG_GETARG_INT32(0);
412+
int i;
413+
int n = pgstat_fetch_stat_numbackends();
414+
415+
for (i = 1; i <= n; i++)
416+
{
417+
PgBackendStatus *be = pgstat_fetch_stat_beentry(i);
418+
if (be)
419+
{
420+
if (be->st_procpid == pid)
421+
{
422+
*(int *)(funcctx->user_fctx) = i;
423+
break;
424+
}
425+
}
426+
}
427+
428+
if (*(int *)(funcctx->user_fctx) == 0)
429+
/* Pid not found, return zero rows */
430+
funcctx->max_calls = 0;
431+
else
432+
funcctx->max_calls = 1;
433+
}
434+
435+
MemoryContextSwitchTo(oldcontext);
436+
}
437+
438+
/* stuff done on every call of the function */
439+
funcctx = SRF_PERCALL_SETUP();
440+
441+
if (funcctx->call_cntr < funcctx->max_calls)
442+
{
443+
/* for each row */
444+
Datum values[10];
445+
bool nulls[10];
446+
HeapTuple tuple;
447+
PgBackendStatus *beentry;
448+
SockAddr zero_clientaddr;
449+
450+
MemSet(values, 0, sizeof(values));
451+
MemSet(nulls, 0, sizeof(nulls));
452+
453+
if (*(int *)(funcctx->user_fctx) > 0)
454+
/* Get specific pid slot */
455+
beentry = pgstat_fetch_stat_beentry(*(int *)(funcctx->user_fctx));
456+
else
457+
/* Get the next one in the list */
458+
beentry = pgstat_fetch_stat_beentry(funcctx->call_cntr+1); /* 1-based index */
459+
if (!beentry)
460+
{
461+
int i;
462+
463+
for (i = 0; i < sizeof(nulls)/sizeof(nulls[0]); i++)
464+
nulls[i] = true;
465+
466+
nulls[3] = false;
467+
values[3] = CStringGetTextDatum("<backend information not available>");
468+
469+
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
470+
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
471+
}
472+
473+
/* Values available to all callers */
474+
values[0] = ObjectIdGetDatum(beentry->st_databaseid);
475+
values[1] = Int32GetDatum(beentry->st_procpid);
476+
values[2] = ObjectIdGetDatum(beentry->st_userid);
477+
478+
/* Values only available to same user or superuser */
479+
if (superuser() || beentry->st_userid == GetUserId())
480+
{
481+
if (*(beentry->st_activity) == '\0')
482+
{
483+
values[3] = CStringGetTextDatum("<command string not enabled>");
484+
}
485+
else
486+
{
487+
values[3] = CStringGetTextDatum(beentry->st_activity);
488+
}
489+
490+
values[4] = BoolGetDatum(beentry->st_waiting);
491+
492+
if (beentry->st_xact_start_timestamp != 0)
493+
values[5] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
494+
else
495+
nulls[5] = true;
496+
497+
if (beentry->st_activity_start_timestamp != 0)
498+
values[6] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
499+
else
500+
nulls[6] = true;
501+
502+
if (beentry->st_proc_start_timestamp != 0)
503+
values[7] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
504+
else
505+
nulls[7] = true;
506+
507+
/* A zeroed client addr means we don't know */
508+
memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
509+
if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
510+
sizeof(zero_clientaddr) == 0))
511+
{
512+
nulls[8] = true;
513+
nulls[9] = true;
514+
}
515+
else
516+
{
517+
if (beentry->st_clientaddr.addr.ss_family == AF_INET
518+
#ifdef HAVE_IPV6
519+
|| beentry->st_clientaddr.addr.ss_family == AF_INET6
520+
#endif
521+
)
522+
{
523+
char remote_host[NI_MAXHOST];
524+
char remote_port[NI_MAXSERV];
525+
int ret;
526+
527+
remote_host[0] = '\0';
528+
remote_port[0] = '\0';
529+
ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
530+
beentry->st_clientaddr.salen,
531+
remote_host, sizeof(remote_host),
532+
remote_port, sizeof(remote_port),
533+
NI_NUMERICHOST | NI_NUMERICSERV);
534+
if (ret)
535+
{
536+
nulls[8] = true;
537+
nulls[9] = true;
538+
}
539+
else
540+
{
541+
clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
542+
values[8] = DirectFunctionCall1(inet_in,
543+
CStringGetDatum(remote_host));
544+
values[9] = Int32GetDatum(atoi(remote_port));
545+
}
546+
}
547+
else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
548+
{
549+
/*
550+
* Unix sockets always reports NULL for host and -1 for port, so it's
551+
* possible to tell the difference to connections we have no
552+
* permissions to view, or with errors.
553+
*/
554+
nulls[8] = true;
555+
values[9] = DatumGetInt32(-1);
556+
}
557+
else
558+
{
559+
/* Unknown address type, should never happen */
560+
nulls[8] = true;
561+
nulls[9] = true;
562+
}
563+
}
564+
}
565+
else
566+
{
567+
/* No permissions to view data about this session */
568+
values[3] = CStringGetTextDatum("<insufficient privilege>");
569+
nulls[4] = true;
570+
nulls[5] = true;
571+
nulls[6] = true;
572+
nulls[7] = true;
573+
nulls[8] = true;
574+
nulls[9] = true;
575+
}
576+
577+
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
578+
579+
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
580+
}
581+
else
582+
{
583+
/* nothing left */
584+
SRF_RETURN_DONE(funcctx);
585+
}
586+
}
587+
366588

367589
Datum
368590
pg_backend_pid(PG_FUNCTION_ARGS)

src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.455 2008/05/04 23:19:23 tgl Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.456 2008/05/07 14:41:55 mha Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 200805042
56+
#define CATALOG_VERSION_NO 200805071
5757

5858
#endif

src/include/catalog/pg_proc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.496 2008/05/04 23:19:23 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.497 2008/05/07 14:41:55 mha Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -2904,6 +2904,8 @@ DATA(insert OID = 2784 ( pg_stat_get_last_autoanalyze_time PGNSP PGUID 12 1 0 f
29042904
DESCR("statistics: last auto analyze time for a table");
29052905
DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 f f t t s 0 23 "" _null_ _null_ _null_ pg_stat_get_backend_idset - _null_ _null_ ));
29062906
DESCR("statistics: currently active backend IDs");
2907+
DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 f f f t s 1 2249 "23" _null_ _null_ _null_ pg_stat_get_activity - _null_ _null_ ));
2908+
DESCR("statistics: information about currently active backends");
29072909
DATA(insert OID = 2026 ( pg_backend_pid PGNSP PGUID 12 1 0 f f t f s 0 23 "" _null_ _null_ _null_ pg_backend_pid - _null_ _null_ ));
29082910
DESCR("statistics: current backend PID");
29092911
DATA(insert OID = 1937 ( pg_stat_get_backend_pid PGNSP PGUID 12 1 0 f f t f s 1 23 "23" _null_ _null_ _null_ pg_stat_get_backend_pid - _null_ _null_ ));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy