]> granicus.if.org Git - postgresql/commitdiff
Separate state from query string in pg_stat_activity
authorMagnus Hagander <magnus@hagander.net>
Thu, 19 Jan 2012 13:19:20 +0000 (14:19 +0100)
committerMagnus Hagander <magnus@hagander.net>
Thu, 19 Jan 2012 13:19:20 +0000 (14:19 +0100)
This separates the state (running/idle/idleintransaction etc) into
it's own field ("state"), and leaves the query field containing just
query text.

The query text will now mean "current query" when a query is running
and "last query" in other states. Accordingly,the field has been
renamed from current_query to query.

Since backwards compatibility was broken anyway to make that, the procpid
field has also been renamed to pid - along with the same field in
pg_stat_replication for consistency.

Scott Mead and Magnus Hagander, review work from Greg Smith

doc/src/sgml/monitoring.sgml
src/backend/catalog/system_views.sql
src/backend/postmaster/autovacuum.c
src/backend/postmaster/pgstat.c
src/backend/tcop/postgres.c
src/backend/utils/adt/pgstatfuncs.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/pgstat.h
src/test/regress/expected/rules.out

index a12a9a2b7263360d0ae32f4088cd223a5f1d536d..225918019d634d2f7915b2d4adbd2f2aa2ba6ca2 100644 (file)
@@ -242,20 +242,20 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
 
     <tbody>
      <row>
-      <entry><structname>pg_stat_activity</><indexterm><primary>pg_stat_activity</primary></indexterm></entry>
-      <entry>One row per server process, showing database OID, database
-      name, process <acronym>ID</>, user OID, user name, application name,
-      client's address, host name (if available), and port number, times at
-      which the server process, current transaction, and current query began
-      execution, process's waiting status, and text of the current query.
-      The columns that report data on the current query are available unless
-      the parameter <varname>track_activities</varname> has been turned off.
-      Furthermore, these columns are only visible if the user examining
-      the view is a superuser or the same as the user owning the process
-      being reported on.  The client's host name will be available only if
-      <xref linkend="guc-log-hostname"> is set or if the user's host name
-      needed to be looked up during <filename>pg_hba.conf</filename>
-      processing.
+      <entry>
+       <structname>pg_stat_activity</structname>
+       <indexterm><primary>pg_stat_activity</primary></indexterm>
+      </entry>
+      <entry>
+       <para>One row per server process, showing information related to
+        each connection to the server. Unless the
+        <xref linkend="guc-track-activities"> parameter has been turned
+         off, it is possible to monitor state and query information of
+         all running processes.
+       </para>
+       <para>
+        See <xref linkend="pg-stat-activity-view"> for more details.
+       </para>
      </entry>
      </row>
 
@@ -529,6 +529,210 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
    into the kernel's handling of I/O.
   </para>
 
+  <table id="pg-stat-activity-view" xreflabel="pg_stat_activity">
+   <title>pg_stat_activity view</title>
+
+   <tgroup cols="3">
+    <thead>
+    <row>
+      <entry>Column</entry>
+      <entry>Type</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+   <tbody>
+    <row>
+     <entry>datid</entry>
+     <entry><type>oid</></entry>
+     <entry>The oid of the database the backend is connected to.</entry>
+    </row>
+    <row>
+     <entry>datname</entry>
+     <entry><type>name</></entry>
+     <entry>The name of the database the backend is connected to.</entry>
+    </row>
+    <row>
+     <entry>pid</entry>
+     <entry><type>integer</></entry>
+     <entry>The process ID of the backend.</entry>
+    </row>
+    <row>
+     <entry>usesysid</entry>
+     <entry><type>oid</></entry>
+     <entry>The id of the user logged into the backend.</entry>
+    </row>
+    <row>
+     <entry>usename</entry>
+     <entry><type>name</></entry>
+     <entry>The name of the user logged into the backend.</entry>
+    </row>
+    <row>
+     <entry>application_name</entry>
+     <entry><type>text</></entry>
+     <entry>The name of the application that has initiated the connection
+      to the backend.</entry>
+    </row>
+    <row>
+     <entry>client_addr</entry>
+     <entry><type>inet</></entry>
+     <entry>The remote IP of the client connected to the backend.
+     If this field is not set, it indicates that the client is either:
+      <itemizedlist spacing="compact" mark="bullet">
+       <listitem>
+        <para>
+         Connected via unix sockets on the server machine
+        </para>
+       </listitem>
+       <listitem>
+        <para>An internal process such as autovacuum</para>
+       </listitem>
+     </itemizedlist>
+     </entry>
+    </row>
+    <row>
+     <entry>client_hostname</entry>
+     <entry><type>text</></entry>
+     <entry>
+      If available, the hostname of the client as reported by a
+      reverse lookup of <structfield>client_addr</>. This field will
+      only be set when <xref linkend="guc-log-hostname"> is enabled.
+     </entry>
+    </row>
+    <row>
+     <entry>client_port</entry>
+     <entry><type>integer</></entry>
+     <entry>
+      The remote TCP port that the client is using for communication
+      to the backend, or <symbol>NULL</> if a unix socket is used.
+     </entry>
+    </row>
+    <row>
+     <entry>backend_start</entry>
+     <entry><type>timestamp with time zone</></entry>
+     <entry>
+      The time when this process was started,  i.e. when the
+      client connected to the server.
+     </entry>
+    </row>
+    <row>
+     <entry>xact_start</entry>
+     <entry><type>timestamp with time zone</></entry>
+     <entry>
+      The time when the current transaction was started. If the client is
+      using autocommit for transactions, this value is equal to the
+      query_start column.
+     </entry>
+    </row>
+    <row>
+     <entry>query_start</entry>
+     <entry><type>timestamp with time zone</></entry>
+     <entry>
+      The time when the currently active query started, or if
+      <structfield>state</> is <literal>idle</>, when the last query
+      was started.
+     </entry>
+    </row>
+    <row>
+     <entry>state_change</entry>
+     <entry><type>timestamp with time zone</></entry>
+     <entry>The time when the <structfield>state</> was last changed.</entry>
+    </row>
+    <row>
+     <entry>waiting</entry>
+     <entry><type>boolean</></entry>
+     <entry>
+      Boolean indicating if a backend is currently waiting on a lock.
+     </entry>
+    </row>
+    <row>
+     <entry>state</entry>
+     <entry><type>text</></entry>
+     <entry>
+       The <structfield>state</> of the currently running query.
+       Can be one of:
+       <variablelist>
+         <varlistentry>
+           <term>active</term>
+           <listitem>
+             <para>
+              The backend is executing a query.
+             </para>
+           </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>idle</term>
+           <listitem>
+             <para>
+               There is no query executing in the backend.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>idle in transaction</term>
+           <listitem>
+             <para>
+               The backend is in a transaction, but is currently not currently
+               executing a query.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>idle in transaction (aborted)</term>
+           <listitem>
+             <para>
+               This state is similar to <literal>idle in transaction</>,
+               except one of the statements in the transaction caused an error.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>fastpath function call</term>
+           <listitem>
+             <para>
+               The backend is executing a fast-path function.
+             </para>
+           </listitem>
+         </varlistentry>
+         <varlistentry>
+           <term>disabled</term>
+           <listitem>
+             <para>
+               This state indicates that <xref linkend="guc-track-activities">
+               is disabled.
+             </para>
+           </listitem>
+         </varlistentry>
+       </variablelist>
+      <note>
+       <para>
+        The <structfield>waiting</> and <structfield>state</> columns are
+        independent.  If a query is in the <literal>active</> state,
+        it may or may not be <literal>waiting</>.  If a query is
+        <literal>active</> and <structfield>waiting</> is true, it means
+        that the query is being executed, but is being blocked by a lock
+        somewhere in the system.
+       </para>
+      </note>
+     </entry>
+    </row>
+    <row>
+     <entry>query</entry>
+     <entry><type>text</></entry>
+     <entry>
+      The most recent query that the backend has executed. If
+      <structfield>state</> is <literal>active</> this means the currently
+      executing query. In all other states, it means the last query that was
+      executed.
+     </entry>
+    </row>
+   </tbody>
+   </tgroup>
+  </table>
+
+ <sect3 id="monitoring-stats-functions">
+  <title>Statistics Access Functions</title>
+
   <para>
    Other ways of looking at the statistics can be set up by writing
    queries that use the same underlying statistics access functions as
@@ -1264,6 +1468,7 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
 </programlisting>
   </para>
 
+ </sect3>
  </sect2>
  </sect1>
 
index 50ba20cce2a8f365de4a04016ad17cc78c678acb..e25914b3065de6b3809ddfb998d7493563f15d06 100644 (file)
@@ -520,7 +520,7 @@ CREATE VIEW pg_stat_activity AS
     SELECT
             S.datid AS datid,
             D.datname AS datname,
-            S.procpid,
+            S.pid,
             S.usesysid,
             U.rolname AS usename,
             S.application_name,
@@ -530,15 +530,17 @@ CREATE VIEW pg_stat_activity AS
             S.backend_start,
             S.xact_start,
             S.query_start,
+            S.state_change,
             S.waiting,
-            S.current_query
+            S.state,
+            S.query
     FROM pg_database D, pg_stat_get_activity(NULL) AS S, pg_authid U
     WHERE S.datid = D.oid AND
             S.usesysid = U.oid;
 
 CREATE VIEW pg_stat_replication AS
     SELECT
-            S.procpid,
+            S.pid,
             S.usesysid,
             U.rolname AS usename,
             S.application_name,
@@ -556,7 +558,7 @@ CREATE VIEW pg_stat_replication AS
     FROM pg_stat_get_activity(NULL) AS S, pg_authid U,
             pg_stat_get_wal_senders() AS W
     WHERE S.usesysid = U.oid AND
-            S.procpid = W.procpid;
+            S.pid = W.pid;
 
 CREATE VIEW pg_stat_database AS
     SELECT
index f858a6df19d57d0adb39ca13659e7e69fa76c979..e84e21c62cd83bb26bd495bcb2568b9dbac62dda 100644 (file)
@@ -2781,7 +2781,7 @@ autovac_report_activity(autovac_table *tab)
        /* Set statement_timestamp() to current time for pg_stat_activity */
        SetCurrentStatementStartTimestamp();
 
-       pgstat_report_activity(activity);
+       pgstat_report_activity(STATE_RUNNING, activity);
 }
 
 /*
index 323d42b5175f097a8a4fb40e4103f170b7ca0f3f..3ab8dfe065b0fc5f12155060c2b4eccf7d6e7876 100644 (file)
@@ -2410,12 +2410,14 @@ pgstat_bestart(void)
        beentry->st_procpid = MyProcPid;
        beentry->st_proc_start_timestamp = proc_start_timestamp;
        beentry->st_activity_start_timestamp = 0;
+       beentry->st_state_start_timestamp = 0;
        beentry->st_xact_start_timestamp = 0;
        beentry->st_databaseid = MyDatabaseId;
        beentry->st_userid = userid;
        beentry->st_clientaddr = clientaddr;
        beentry->st_clienthostname[0] = '\0';
        beentry->st_waiting = false;
+       beentry->st_state = STATE_UNDEFINED;
        beentry->st_appname[0] = '\0';
        beentry->st_activity[0] = '\0';
        /* Also make sure the last byte in each string area is always 0 */
@@ -2476,39 +2478,70 @@ pgstat_beshutdown_hook(int code, Datum arg)
  *
  *     Called from tcop/postgres.c to report what the backend is actually doing
  *     (usually "<IDLE>" or the start of the query to be executed).
+ *
+ * All updates of the status entry follow the protocol of bumping
+ * st_changecount before and after.  We use a volatile pointer here to
+ * ensure the compiler doesn't try to get cute.
  * ----------
  */
 void
-pgstat_report_activity(const char *cmd_str)
+pgstat_report_activity(BackendState state, const char *cmd_str)
 {
        volatile PgBackendStatus *beentry = MyBEEntry;
        TimestampTz start_timestamp;
+       TimestampTz current_timestamp;
        int                     len;
 
        TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str);
 
-       if (!pgstat_track_activities || !beentry)
+       if (!beentry)
                return;
 
        /*
         * To minimize the time spent modifying the entry, fetch all the needed
         * data first.
         */
-       start_timestamp = GetCurrentStatementStartTimestamp();
+       current_timestamp = GetCurrentTimestamp();
 
-       len = strlen(cmd_str);
-       len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1);
+       if (!pgstat_track_activities && beentry->st_state != STATE_DISABLED)
+       {
+               /*
+                * Track activities is disabled, but we have a non-disabled state set.
+                * That means the status changed - so as our last update, tell the
+                * collector that we disabled it and will no longer update.
+                */
+               beentry->st_changecount++;
+               beentry->st_state = STATE_DISABLED;
+               beentry->st_state_start_timestamp = current_timestamp;
+               beentry->st_changecount++;
+               Assert((beentry->st_changecount & 1) == 0);
+               return;
+       }
 
        /*
-        * Update my status entry, following the protocol of bumping
-        * st_changecount before and after.  We use a volatile pointer here to
-        * ensure the compiler doesn't try to get cute.
+        * Fetch more data before we start modifying the entry
+        */
+       start_timestamp = GetCurrentStatementStartTimestamp();
+       if (cmd_str != NULL)
+       {
+               len = strlen(cmd_str);
+               len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1);
+       }
+
+       /*
+        * Now update the status entry
         */
        beentry->st_changecount++;
 
-       beentry->st_activity_start_timestamp = start_timestamp;
-       memcpy((char *) beentry->st_activity, cmd_str, len);
-       beentry->st_activity[len] = '\0';
+       beentry->st_state = state;
+       beentry->st_state_start_timestamp = current_timestamp;
+
+       if (cmd_str != NULL)
+       {
+               memcpy((char *) beentry->st_activity, cmd_str, len);
+               beentry->st_activity[len] = '\0';
+               beentry->st_activity_start_timestamp = start_timestamp;
+       }
 
        beentry->st_changecount++;
        Assert((beentry->st_changecount & 1) == 0);
index 59a287f79bf724664d789d573f1d0058f22ac903..49a396918d9bd3ed2bfc228369ced0c497ee09c9 100644 (file)
@@ -809,7 +809,7 @@ exec_simple_query(const char *query_string)
         */
        debug_query_string = query_string;
 
-       pgstat_report_activity(query_string);
+       pgstat_report_activity(STATE_RUNNING, query_string);
 
        TRACE_POSTGRESQL_QUERY_START(query_string);
 
@@ -1134,7 +1134,7 @@ exec_parse_message(const char *query_string,      /* string to execute */
         */
        debug_query_string = query_string;
 
-       pgstat_report_activity(query_string);
+       pgstat_report_activity(STATE_RUNNING, query_string);
 
        set_ps_display("PARSE", false);
 
@@ -1429,7 +1429,7 @@ exec_bind_message(StringInfo input_message)
         */
        debug_query_string = psrc->query_string;
 
-       pgstat_report_activity(psrc->query_string);
+       pgstat_report_activity(STATE_RUNNING, psrc->query_string);
 
        set_ps_display("BIND", false);
 
@@ -1836,7 +1836,7 @@ exec_execute_message(const char *portal_name, long max_rows)
         */
        debug_query_string = sourceText;
 
-       pgstat_report_activity(sourceText);
+       pgstat_report_activity(STATE_RUNNING, sourceText);
 
        set_ps_display(portal->commandTag, false);
 
@@ -3811,12 +3811,12 @@ PostgresMain(int argc, char *argv[], const char *username)
                        if (IsAbortedTransactionBlockState())
                        {
                                set_ps_display("idle in transaction (aborted)", false);
-                               pgstat_report_activity("<IDLE> in transaction (aborted)");
+                               pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
                        }
                        else if (IsTransactionOrTransactionBlock())
                        {
                                set_ps_display("idle in transaction", false);
-                               pgstat_report_activity("<IDLE> in transaction");
+                               pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
                        }
                        else
                        {
@@ -3824,7 +3824,7 @@ PostgresMain(int argc, char *argv[], const char *username)
                                pgstat_report_stat(false);
 
                                set_ps_display("idle", false);
-                               pgstat_report_activity("<IDLE>");
+                               pgstat_report_activity(STATE_IDLE, NULL);
                        }
 
                        ReadyForQuery(whereToSendOutput);
@@ -3944,7 +3944,7 @@ PostgresMain(int argc, char *argv[], const char *username)
                                SetCurrentStatementStartTimestamp();
 
                                /* Report query to various monitoring facilities. */
-                               pgstat_report_activity("<FASTPATH> function call");
+                               pgstat_report_activity(STATE_FASTPATH, NULL);
                                set_ps_display("<FASTPATH>", false);
 
                                /* start an xact for this function invocation */
index b4986d80bab715e5558cbd64338357e9d5fcead9..ed39f27ef48cc620f4b26a54b8524c452dc7ecea 100644 (file)
@@ -507,31 +507,34 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 
                oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-               tupdesc = CreateTemplateTupleDesc(12, false);
+               tupdesc = CreateTemplateTupleDesc(14, false);
                TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
                                                   OIDOID, -1, 0);
-               /* This should have been called 'pid';  can't change it. 2011-06-11 */
-               TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 2, "pid",
                                                   INT4OID, -1, 0);
                TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid",
                                                   OIDOID, -1, 0);
                TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name",
                                                   TEXTOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 5, "current_query",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 5, "state",
                                                   TEXTOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 6, "waiting",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 6, "query",
+                                                  TEXTOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 7, "waiting",
                                                   BOOLOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 7, "act_start",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 8, "act_start",
+                                                  TIMESTAMPTZOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 9, "query_start",
                                                   TIMESTAMPTZOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 10, "backend_start",
                                                   TIMESTAMPTZOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 11, "state_change",
                                                   TIMESTAMPTZOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_addr",
                                                   INETOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_hostname",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 13, "client_hostname",
                                                   TEXTOID, -1, 0);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_port",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 14, "client_port",
                                                   INT4OID, -1, 0);
 
                funcctx->tuple_desc = BlessTupleDesc(tupdesc);
@@ -584,8 +587,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
        if (funcctx->call_cntr < funcctx->max_calls)
        {
                /* for each row */
-               Datum           values[12];
-               bool            nulls[12];
+               Datum           values[14];
+               bool            nulls[14];
                HeapTuple       tuple;
                PgBackendStatus *beentry;
                SockAddr        zero_clientaddr;
@@ -610,8 +613,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                        for (i = 0; i < sizeof(nulls) / sizeof(nulls[0]); i++)
                                nulls[i] = true;
 
-                       nulls[4] = false;
-                       values[4] = CStringGetTextDatum("<backend information not available>");
+                       nulls[5] = false;
+                       values[5] = CStringGetTextDatum("<backend information not available>");
 
                        tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
                        SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
@@ -629,40 +632,69 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                /* Values only available to same user or superuser */
                if (superuser() || beentry->st_userid == GetUserId())
                {
-                       if (*(beentry->st_activity) == '\0')
+                       switch (beentry->st_state)
+                       {
+                               case STATE_IDLE:
+                                       values[4] = CStringGetTextDatum("idle");
+                                       break;
+                               case STATE_RUNNING:
+                                       values[4] = CStringGetTextDatum("active");
+                                       break;
+                               case STATE_IDLEINTRANSACTION:
+                                       values[4] = CStringGetTextDatum("idle in transaction");
+                                       break;
+                               case STATE_FASTPATH:
+                                       values[4] = CStringGetTextDatum("fastpath function call");
+                                       break;
+                               case STATE_IDLEINTRANSACTION_ABORTED:
+                                       values[4] = CStringGetTextDatum("idle in transaction (aborted)");
+                                       break;
+                               case STATE_DISABLED:
+                                       values[4] = CStringGetTextDatum("disabled");
+                                       break;
+                               case STATE_UNDEFINED:
+                                       nulls[4] = true;
+                                       break;
+                       }
+                       if (beentry->st_state == STATE_UNDEFINED ||
+                               beentry->st_state == STATE_DISABLED)
                        {
-                               values[4] = CStringGetTextDatum("<command string not enabled>");
+                               values[5] = CStringGetTextDatum("");
                        }
                        else
                        {
-                               values[4] = CStringGetTextDatum(beentry->st_activity);
+                               values[5] = CStringGetTextDatum(beentry->st_activity);
                        }
-
-                       values[5] = BoolGetDatum(beentry->st_waiting);
+                       values[6] = BoolGetDatum(beentry->st_waiting);
 
                        if (beentry->st_xact_start_timestamp != 0)
-                               values[6] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
+                               values[7] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
                        else
-                               nulls[6] = true;
+                               nulls[7] = true;
 
                        if (beentry->st_activity_start_timestamp != 0)
-                               values[7] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
+                               values[8] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
                        else
-                               nulls[7] = true;
+                               nulls[8] = true;
 
                        if (beentry->st_proc_start_timestamp != 0)
-                               values[8] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
+                               values[9] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
                        else
-                               nulls[8] = true;
+                               nulls[9] = true;
+
+                       if (beentry->st_state_start_timestamp != 0)
+                               values[10] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
+                       else
+                               nulls[10] = true;
 
                        /* A zeroed client addr means we don't know */
                        memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
                        if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
                                           sizeof(zero_clientaddr) == 0))
                        {
-                               nulls[9] = true;
-                               nulls[10] = true;
                                nulls[11] = true;
+                               nulls[12] = true;
+                               nulls[13] = true;
                        }
                        else
                        {
@@ -686,19 +718,19 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                                        if (ret == 0)
                                        {
                                                clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
-                                               values[9] = DirectFunctionCall1(inet_in,
+                                               values[11] = DirectFunctionCall1(inet_in,
                                                                                           CStringGetDatum(remote_host));
                                                if (beentry->st_clienthostname)
-                                                       values[10] = CStringGetTextDatum(beentry->st_clienthostname);
+                                                       values[12] = CStringGetTextDatum(beentry->st_clienthostname);
                                                else
-                                                       nulls[10] = true;
-                                               values[11] = Int32GetDatum(atoi(remote_port));
+                                                       nulls[12] = true;
+                                               values[13] = Int32GetDatum(atoi(remote_port));
                                        }
                                        else
                                        {
-                                               nulls[9] = true;
-                                               nulls[10] = true;
                                                nulls[11] = true;
+                                               nulls[12] = true;
+                                               nulls[13] = true;
                                        }
                                }
                                else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
@@ -709,30 +741,32 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                                         * connections we have no permissions to view, or with
                                         * errors.
                                         */
-                                       nulls[9] = true;
-                                       nulls[10] = true;
-                                       values[11] = DatumGetInt32(-1);
+                                       nulls[11] = true;
+                                       nulls[12] = true;
+                                       values[13] = DatumGetInt32(-1);
                                }
                                else
                                {
                                        /* Unknown address type, should never happen */
-                                       nulls[9] = true;
-                                       nulls[10] = true;
                                        nulls[11] = true;
+                                       nulls[12] = true;
+                                       nulls[13] = true;
                                }
                        }
                }
                else
                {
                        /* No permissions to view data about this session */
-                       values[4] = CStringGetTextDatum("<insufficient privilege>");
-                       nulls[5] = true;
+                       values[5] = CStringGetTextDatum("<insufficient privilege>");
+                       nulls[4] = true;
                        nulls[6] = true;
                        nulls[7] = true;
                        nulls[8] = true;
                        nulls[9] = true;
                        nulls[10] = true;
                        nulls[11] = true;
+                       nulls[12] = true;
+                       nulls[13] = true;
                }
 
                tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
index f7af5fdbc4b67dcefe3a11892ba71b739efe7706..9e799c6a1037f84c322982316ea7d1154ee9ec61 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201112241
+#define CATALOG_VERSION_NO     201201191
 
 #endif
index 355c61a62337d7f0e8c9461369c421319e9673d8..9994468571c1ab4b6bc914970cb84836d992ea75 100644 (file)
@@ -2573,9 +2573,9 @@ DATA(insert OID = 3057 ( pg_stat_get_autoanalyze_count PGNSP PGUID 12 1 0 0 0 f
 DESCR("statistics: number of auto analyzes for a table");
 DATA(insert OID = 1936 (  pg_stat_get_backend_idset            PGNSP PGUID 12 1 100 0 0 f f f t t s 0 0 23 "" _null_ _null_ _null_ _null_ pg_stat_get_backend_idset _null_ _null_ _null_ ));
 DESCR("statistics: currently active backend IDs");
-DATA(insert OID = 2022 (  pg_stat_get_activity                 PGNSP PGUID 12 1 100 0 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_hostname,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
+DATA(insert OID = 2022 (  pg_stat_get_activity                 PGNSP PGUID 12 1 100 0 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,1184,869,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,waiting,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
 DESCR("statistics: information about currently active backends");
-DATA(insert OID = 3099 (  pg_stat_get_wal_senders      PGNSP PGUID 12 1 10 0 0 f f f f t s 0 0 2249 "" "{23,25,25,25,25,25,23,25}" "{o,o,o,o,o,o,o,o}" "{procpid,state,sent_location,write_location,flush_location,replay_location,sync_priority,sync_state}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
+DATA(insert OID = 3099 (  pg_stat_get_wal_senders      PGNSP PGUID 12 1 10 0 0 f f f f t s 0 0 2249 "" "{23,25,25,25,25,25,23,25}" "{o,o,o,o,o,o,o,o}" "{pid,state,sent_location,write_location,flush_location,replay_location,sync_priority,sync_state}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
 DESCR("statistics: information about currently active replication");
 DATA(insert OID = 2026 (  pg_backend_pid                               PGNSP PGUID 12 1 0 0 0 f f f t f s 0 0 23 "" _null_ _null_ _null_ _null_ pg_backend_pid _null_ _null_ _null_ ));
 DESCR("statistics: current backend PID");
index b8c6d82d0ea5411f68f54ee1b2fa986317e83908..fa52447048dea94dbabf27a0bf7d532b498e6ba0 100644 (file)
@@ -588,11 +588,26 @@ typedef struct PgStat_GlobalStats
 } PgStat_GlobalStats;
 
 
+/* ----------
+ * Backend states
+ * ----------
+ */
+typedef enum BackendState {
+       STATE_UNDEFINED,
+       STATE_IDLE,
+       STATE_RUNNING,
+       STATE_IDLEINTRANSACTION,
+       STATE_FASTPATH,
+       STATE_IDLEINTRANSACTION_ABORTED,
+       STATE_DISABLED,
+} BackendState;
+
 /* ----------
  * Shared-memory data structures
  * ----------
  */
 
+
 /* ----------
  * PgBackendStatus
  *
@@ -622,6 +637,7 @@ typedef struct PgBackendStatus
        TimestampTz st_proc_start_timestamp;
        TimestampTz st_xact_start_timestamp;
        TimestampTz st_activity_start_timestamp;
+    TimestampTz st_state_start_timestamp;
 
        /* Database OID, owning user's OID, connection client address */
        Oid                     st_databaseid;
@@ -632,6 +648,9 @@ typedef struct PgBackendStatus
        /* Is backend currently waiting on an lmgr lock? */
        bool            st_waiting;
 
+    /* current state */
+    BackendState       st_state;
+
        /* application name; MUST be null-terminated */
        char       *st_appname;
 
@@ -715,7 +734,7 @@ extern void pgstat_report_recovery_conflict(int reason);
 extern void pgstat_initialize(void);
 extern void pgstat_bestart(void);
 
-extern void pgstat_report_activity(const char *cmd_str);
+extern void pgstat_report_activity(BackendState state, const char *cmd_str);
 extern void pgstat_report_appname(const char *appname);
 extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
 extern void pgstat_report_waiting(bool waiting);
index 454e1f98e45e77a331adbc054007a1c502d6a519..d26881f887434abe22cb8e7223b549b4e1e27c82 100644 (file)
@@ -1292,13 +1292,13 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
  pg_seclabels                    | ((((((((SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (rel.relkind = 'r'::"char") THEN 'table'::text WHEN (rel.relkind = 'v'::"char") THEN 'view'::text WHEN (rel.relkind = 'S'::"char") THEN 'sequence'::text WHEN (rel.relkind = 'f'::"char") THEN 'foreign table'::text ELSE NULL::text END AS objtype, rel.relnamespace AS objnamespace, CASE WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text)) END AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid)))) JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid))) WHERE (l.objsubid = 0) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'column'::text AS objtype, rel.relnamespace AS objnamespace, ((CASE WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text)) END || '.'::text) || (att.attname)::text) AS objname, l.provider, l.label FROM (((pg_seclabel l JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid)))) JOIN pg_attribute att ON (((rel.oid = att.attrelid) AND (l.objsubid = att.attnum)))) JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid))) WHERE (l.objsubid <> 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (pro.proisagg = true) THEN 'aggregate'::text WHEN (pro.proisagg = false) THEN 'function'::text ELSE NULL::text END AS objtype, pro.pronamespace AS objnamespace, (((CASE WHEN pg_function_is_visible(pro.oid) THEN quote_ident((pro.proname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((pro.proname)::text)) END || '('::text) || pg_get_function_arguments(pro.oid)) || ')'::text) AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_proc pro ON (((l.classoid = pro.tableoid) AND (l.objoid = pro.oid)))) JOIN pg_namespace nsp ON ((pro.pronamespace = nsp.oid))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (typ.typtype = 'd'::"char") THEN 'domain'::text ELSE 'type'::text END AS objtype, typ.typnamespace AS objnamespace, CASE WHEN pg_type_is_visible(typ.oid) THEN quote_ident((typ.typname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((typ.typname)::text)) END AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_type typ ON (((l.classoid = typ.tableoid) AND (l.objoid = typ.oid)))) JOIN pg_namespace nsp ON ((typ.typnamespace = nsp.oid))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'large object'::text AS objtype, NULL::oid AS objnamespace, (l.objoid)::text AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_largeobject_metadata lom ON ((l.objoid = lom.oid))) WHERE ((l.classoid = ('pg_largeobject'::regclass)::oid) AND (l.objsubid = 0))) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'language'::text AS objtype, NULL::oid AS objnamespace, quote_ident((lan.lanname)::text) AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_language lan ON (((l.classoid = lan.tableoid) AND (l.objoid = lan.oid)))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'schema'::text AS objtype, nsp.oid AS objnamespace, quote_ident((nsp.nspname)::text) AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_namespace nsp ON (((l.classoid = nsp.tableoid) AND (l.objoid = nsp.oid)))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, 0 AS objsubid, 'database'::text AS objtype, NULL::oid AS objnamespace, quote_ident((dat.datname)::text) AS objname, l.provider, l.label FROM (pg_shseclabel l JOIN pg_database dat ON (((l.classoid = dat.tableoid) AND (l.objoid = dat.oid))))) UNION ALL SELECT l.objoid, l.classoid, 0 AS objsubid, 'tablespace'::text AS objtype, NULL::oid AS objnamespace, quote_ident((spc.spcname)::text) AS objname, l.provider, l.label FROM (pg_shseclabel l JOIN pg_tablespace spc ON (((l.classoid = spc.tableoid) AND (l.objoid = spc.oid))))) UNION ALL SELECT l.objoid, l.classoid, 0 AS objsubid, 'role'::text AS objtype, NULL::oid AS objnamespace, quote_ident((rol.rolname)::text) AS objname, l.provider, l.label FROM (pg_shseclabel l JOIN pg_authid rol ON (((l.classoid = rol.tableoid) AND (l.objoid = rol.oid))));
  pg_settings                     | SELECT a.name, a.setting, a.unit, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val, a.enumvals, a.boot_val, a.reset_val, a.sourcefile, a.sourceline FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, sourcefile, sourceline);
  pg_shadow                       | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolreplication AS userepl, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, s.setconfig AS useconfig FROM (pg_authid LEFT JOIN pg_db_role_setting s ON (((pg_authid.oid = s.setrole) AND (s.setdatabase = (0)::oid)))) WHERE pg_authid.rolcanlogin;
- pg_stat_activity                | SELECT s.datid, d.datname, s.procpid, s.usesysid, u.rolname AS usename, s.application_name, s.client_addr, s.client_hostname, s.client_port, s.backend_start, s.xact_start, s.query_start, s.waiting, s.current_query FROM pg_database d, pg_stat_get_activity(NULL::integer) s(datid, procpid, usesysid, application_name, current_query, waiting, xact_start, query_start, backend_start, client_addr, client_hostname, client_port), pg_authid u WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid));
+ pg_stat_activity                | SELECT s.datid, d.datname, s.pid, s.usesysid, u.rolname AS usename, s.application_name, s.client_addr, s.client_hostname, s.client_port, s.backend_start, s.xact_start, s.query_start, s.state_change, s.waiting, s.state, s.query FROM pg_database d, pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port), pg_authid u WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid));
  pg_stat_all_indexes             | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"]));
  pg_stat_all_tables              | SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, pg_stat_get_numscans(c.oid) AS seq_scan, pg_stat_get_tuples_returned(c.oid) AS seq_tup_read, (sum(pg_stat_get_numscans(i.indexrelid)))::bigint AS idx_scan, ((sum(pg_stat_get_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_tuples_fetched(c.oid)) AS idx_tup_fetch, pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins, pg_stat_get_tuples_updated(c.oid) AS n_tup_upd, pg_stat_get_tuples_deleted(c.oid) AS n_tup_del, pg_stat_get_tuples_hot_updated(c.oid) AS n_tup_hot_upd, pg_stat_get_live_tuples(c.oid) AS n_live_tup, pg_stat_get_dead_tuples(c.oid) AS n_dead_tup, pg_stat_get_last_vacuum_time(c.oid) AS last_vacuum, pg_stat_get_last_autovacuum_time(c.oid) AS last_autovacuum, pg_stat_get_last_analyze_time(c.oid) AS last_analyze, pg_stat_get_last_autoanalyze_time(c.oid) AS last_autoanalyze, pg_stat_get_vacuum_count(c.oid) AS vacuum_count, pg_stat_get_autovacuum_count(c.oid) AS autovacuum_count, pg_stat_get_analyze_count(c.oid) AS analyze_count, pg_stat_get_autoanalyze_count(c.oid) AS autoanalyze_count FROM ((pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"])) GROUP BY c.oid, n.nspname, c.relname;
  pg_stat_bgwriter                | SELECT pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed, pg_stat_get_bgwriter_requested_checkpoints() AS checkpoints_req, pg_stat_get_bgwriter_buf_written_checkpoints() AS buffers_checkpoint, pg_stat_get_bgwriter_buf_written_clean() AS buffers_clean, pg_stat_get_bgwriter_maxwritten_clean() AS maxwritten_clean, pg_stat_get_buf_written_backend() AS buffers_backend, pg_stat_get_buf_fsync_backend() AS buffers_backend_fsync, pg_stat_get_buf_alloc() AS buffers_alloc, pg_stat_get_bgwriter_stat_reset_time() AS stats_reset;
  pg_stat_database                | SELECT d.oid AS datid, d.datname, pg_stat_get_db_numbackends(d.oid) AS numbackends, pg_stat_get_db_xact_commit(d.oid) AS xact_commit, pg_stat_get_db_xact_rollback(d.oid) AS xact_rollback, (pg_stat_get_db_blocks_fetched(d.oid) - pg_stat_get_db_blocks_hit(d.oid)) AS blks_read, pg_stat_get_db_blocks_hit(d.oid) AS blks_hit, pg_stat_get_db_tuples_returned(d.oid) AS tup_returned, pg_stat_get_db_tuples_fetched(d.oid) AS tup_fetched, pg_stat_get_db_tuples_inserted(d.oid) AS tup_inserted, pg_stat_get_db_tuples_updated(d.oid) AS tup_updated, pg_stat_get_db_tuples_deleted(d.oid) AS tup_deleted, pg_stat_get_db_conflict_all(d.oid) AS conflicts, pg_stat_get_db_stat_reset_time(d.oid) AS stats_reset FROM pg_database d;
  pg_stat_database_conflicts      | SELECT d.oid AS datid, d.datname, pg_stat_get_db_conflict_tablespace(d.oid) AS confl_tablespace, pg_stat_get_db_conflict_lock(d.oid) AS confl_lock, pg_stat_get_db_conflict_snapshot(d.oid) AS confl_snapshot, pg_stat_get_db_conflict_bufferpin(d.oid) AS confl_bufferpin, pg_stat_get_db_conflict_startup_deadlock(d.oid) AS confl_deadlock FROM pg_database d;
- pg_stat_replication             | SELECT s.procpid, s.usesysid, u.rolname AS usename, s.application_name, s.client_addr, s.client_hostname, s.client_port, s.backend_start, w.state, w.sent_location, w.write_location, w.flush_location, w.replay_location, w.sync_priority, w.sync_state FROM pg_stat_get_activity(NULL::integer) s(datid, procpid, usesysid, application_name, current_query, waiting, xact_start, query_start, backend_start, client_addr, client_hostname, client_port), pg_authid u, pg_stat_get_wal_senders() w(procpid, state, sent_location, write_location, flush_location, replay_location, sync_priority, sync_state) WHERE ((s.usesysid = u.oid) AND (s.procpid = w.procpid));
+ pg_stat_replication             | SELECT s.pid, s.usesysid, u.rolname AS usename, s.application_name, s.client_addr, s.client_hostname, s.client_port, s.backend_start, w.state, w.sent_location, w.write_location, w.flush_location, w.replay_location, w.sync_priority, w.sync_state FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port), pg_authid u, pg_stat_get_wal_senders() w(pid, state, sent_location, write_location, flush_location, replay_location, sync_priority, sync_state) WHERE ((s.usesysid = u.oid) AND (s.pid = w.pid));
  pg_stat_sys_indexes             | SELECT pg_stat_all_indexes.relid, pg_stat_all_indexes.indexrelid, pg_stat_all_indexes.schemaname, pg_stat_all_indexes.relname, pg_stat_all_indexes.indexrelname, pg_stat_all_indexes.idx_scan, pg_stat_all_indexes.idx_tup_read, pg_stat_all_indexes.idx_tup_fetch FROM pg_stat_all_indexes WHERE ((pg_stat_all_indexes.schemaname = ANY (ARRAY['pg_catalog'::name, 'information_schema'::name])) OR (pg_stat_all_indexes.schemaname ~ '^pg_toast'::text));
  pg_stat_sys_tables              | SELECT pg_stat_all_tables.relid, pg_stat_all_tables.schemaname, pg_stat_all_tables.relname, pg_stat_all_tables.seq_scan, pg_stat_all_tables.seq_tup_read, pg_stat_all_tables.idx_scan, pg_stat_all_tables.idx_tup_fetch, pg_stat_all_tables.n_tup_ins, pg_stat_all_tables.n_tup_upd, pg_stat_all_tables.n_tup_del, pg_stat_all_tables.n_tup_hot_upd, pg_stat_all_tables.n_live_tup, pg_stat_all_tables.n_dead_tup, pg_stat_all_tables.last_vacuum, pg_stat_all_tables.last_autovacuum, pg_stat_all_tables.last_analyze, pg_stat_all_tables.last_autoanalyze, pg_stat_all_tables.vacuum_count, pg_stat_all_tables.autovacuum_count, pg_stat_all_tables.analyze_count, pg_stat_all_tables.autoanalyze_count FROM pg_stat_all_tables WHERE ((pg_stat_all_tables.schemaname = ANY (ARRAY['pg_catalog'::name, 'information_schema'::name])) OR (pg_stat_all_tables.schemaname ~ '^pg_toast'::text));
  pg_stat_user_functions          | SELECT p.oid AS funcid, n.nspname AS schemaname, p.proname AS funcname, pg_stat_get_function_calls(p.oid) AS calls, (pg_stat_get_function_time(p.oid) / 1000) AS total_time, (pg_stat_get_function_self_time(p.oid) / 1000) AS self_time FROM (pg_proc p LEFT JOIN pg_namespace n ON ((n.oid = p.pronamespace))) WHERE ((p.prolang <> (12)::oid) AND (pg_stat_get_function_calls(p.oid) IS NOT NULL));