Re: ALTER SESSION

Поиск
Список
Период
Сортировка
От Kyotaro HORIGUCHI
Тема Re: ALTER SESSION
Дата
Msg-id 20190130.124857.114645212.horiguchi.kyotaro@lab.ntt.co.jp
обсуждение исходный текст
Ответ на Re: ALTER SESSION  (Stephen Frost <sfrost@snowman.net>)
Ответы RE: ALTER SESSION  ("Tsunakawa, Takayuki" <tsunakawa.takay@jp.fujitsu.com>)
Список pgsql-hackers
At Tue, 29 Jan 2019 21:46:28 -0500, Stephen Frost <sfrost@snowman.net> wrote in
<20190130024628.GE5118@tamriel.snowman.net>
> Greetings,
> 
> * Andres Freund (andres@anarazel.de) wrote:
> > On 2019-01-29 21:09:22 -0500, Stephen Frost wrote:
> > > * Andres Freund (andres@anarazel.de) wrote:
> > > > On 2019-01-29 20:52:08 -0500, Stephen Frost wrote:
> > > > > * Andres Freund (andres@anarazel.de) wrote:
> > > > > > Leaving the desirability of the feature aside, isn't this racy as hell?
> > > > > > I.e. it seems entirely possible that backends stop/start between
> > > > > > determining the PID, and the ALTER SESSION creating the file, and it
> > > > > > actually being processed. By the time that happens an entirely different
> > > > > > session might be using that pid.
> > > > > 
> > > > > That seems like something that could possibly be fixed, by adding in
> > > > > other things to make it more likely to be the 'right' backend, but my
> > > > > complaint here is that we are, again, using files to pass data between
> > > > > backend processes and that seems like a pretty terrible direction to be
> > > > > going in.
> > > > 
> > > > I think pid would be wholly unsuitable for this, and if so we'd have to
> > > > use something entirely independent.
> > > 
> > > I would think you'd use pid + other stuff (user OID, backend proc entry
> > > number, other things).  Basically, if you see a file there with your pid
> > > on it, then you look and see if the other things match- if so, act on
> > > it, if not, discard the file.  I still don't like this approach though,
> > 
> > What do we gain by including the pid here? Seems much more reasonable to
> > use a session id that's just unique over the life of a cluster.
> 
> Are you suggesting we have one of those already, or is the idea that
> we'd add a cluster-lifetime session id for this?

Just a 32 bit counter would suffice for such a period. But in the
attached the worst thing to happen is that the new session reads
the only one config line written by the last command, which don't
seem harmful.. (Of couse not the best, though.)

> > > I really don't think files are the right way to be going about this.
> > 
> > Why? They persist and can be removed, they are introspectable, they
> > automatically are removed from memory when there's no demand...
> 
> Well, we don't actually want these to persist, and it's because they do
> that we have to deal with removing them, and I don't see a whole lot of
> gain from them being introspectable; indeed, that seems like more of a
> drawback than anything since it will invite people to whack those files
> around and abuse them as if they were some externally documented
> interface.

.auto.conf is already a kind of such.. My first version signals
the change via shared memory (in a largely-improvable way) and
add the GUC system the complex "nontransactional SET" feature,
which lets a change persists beyond transaction end if
any. Holding changes until the session becomes idle seems also
complex.

https://www.postgresql.org/message-id/20181127.193622.252197705.horiguchi.kyotaro@lab.ntt.co.jp

The most significant reason for passing-by-file is the affinity
with the current GUC system.

> They also cost disk space, they require inodes, they have to be cleaned
> up and managed on shutdown/restart, backup tools need to understand what
> to do with them, potentially, we have to consider if we should have a
> checksum for them, we have to handle out-of-disk space cases with them,
> they could cause us to run out of disk space...

The files are so small to cause such problems easily, but I agree
that file handling is bothersome and fragile. A weak point of
signalling via shared memory is incompatibility with the current
GUC system as I mentioned above.

> These same arguments could have been made about how we could have
> implemented parallel query too.  I agree that the use-case is somewhat
> different there but there's also a lot of similarity when it comes to
> managing this passing of information to that use-case.

Parallel query passes data via DSM?

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
From ceabf24d061a15ed39db544a0972ba199ce2c4bf Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Tue, 29 Jan 2019 17:03:57 +0900
Subject: [PATCH] ALTER SESSION

Some tracking features are controled by GUC so they cannot be
activated from another session. The ALTER SESSION command allows
sessions to change some of GUC settings of another session.
---
 doc/src/sgml/config.sgml             |  26 ++-
 doc/src/sgml/ref/allfiles.sgml       |   1 +
 doc/src/sgml/ref/alter_session.sgml  | 160 ++++++++++++++++
 doc/src/sgml/reference.sgml          |   1 +
 src/backend/nodes/copyfuncs.c        |  14 ++
 src/backend/nodes/equalfuncs.c       |  12 ++
 src/backend/parser/gram.y            |  51 ++++-
 src/backend/postmaster/postmaster.c  |   6 +
 src/backend/replication/basebackup.c |   3 +
 src/backend/tcop/utility.c           |  13 ++
 src/backend/utils/init/postinit.c    |   3 +
 src/backend/utils/misc/guc-file.l    |  23 +++
 src/backend/utils/misc/guc.c         | 349 +++++++++++++++++++++++++++--------
 src/bin/initdb/initdb.c              |   3 +-
 src/include/nodes/nodes.h            |   1 +
 src/include/nodes/parsenodes.h       |  12 ++
 src/include/parser/kwlist.h          |   1 +
 src/include/utils/guc.h              |  13 ++
 18 files changed, 612 insertions(+), 80 deletions(-)
 create mode 100644 doc/src/sgml/ref/alter_session.sgml

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index b6f5822b84..a52989342a 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -175,6 +175,14 @@ shared_buffers = 128MB
      read whenever <filename>postgresql.conf</filename> is, and its settings take
      effect in the same way.  Settings in <filename>postgresql.auto.conf</filename>
      override those in <filename>postgresql.conf</filename>.
+
+    </para>
+    <para>
+     Furthermore a directory <filename>pg_session_conf</filename> in the
+     PostgreSQL data directory contains per-session configuration files. Every
+     file holds settings provided through the
+     <xref linkend="sql-altersession"/> command. This is read by reloading
+     after the two above files and removed at the session-end.
     </para>
 
     <para>
@@ -195,8 +203,8 @@ shared_buffers = 128MB
       The already-mentioned <xref linkend="sql-altersystem"/> command
       provides a SQL-accessible means of changing global defaults; it is
       functionally equivalent to editing <filename>postgresql.conf</filename>.
-      In addition, there are two commands that allow setting of defaults
-      on a per-database or per-role basis:
+      In addition, there are three commands that allow setting of defaults
+      on a per-database, per-role or per-session basis:
      </para>
 
      <itemizedlist>
@@ -213,6 +221,13 @@ shared_buffers = 128MB
        per-database settings to be overridden with user-specific values.
       </para>
      </listitem>
+
+     <listitem>
+      <para>
+       The <xref linkend="sql-altersession"/> command allows other sessions to
+        override session-local settings with user-specific values.
+      </para>
+     </listitem>
     </itemizedlist>
 
      <para>
@@ -223,6 +238,13 @@ shared_buffers = 128MB
       Note that some settings cannot be changed after server start, and
       so cannot be set with these commands (or the ones listed below).
     </para>
+     <para>
+      Values set with <command>ALTER SESSION</command> are applied only when
+      reloading.  They override values obtained from the configuration files
+      or server command line, and constitute defaults for the rest of the
+      session.  Note that it can change only settings that are changeable
+      on-session.
+    </para>
 
      <para>
       Once a client is connected to the database, <productname>PostgreSQL</productname>
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index c81c87ef41..650ae49a24 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -34,6 +34,7 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY alterSchema        SYSTEM "alter_schema.sgml">
 <!ENTITY alterServer        SYSTEM "alter_server.sgml">
 <!ENTITY alterSequence      SYSTEM "alter_sequence.sgml">
+<!ENTITY alterSession       SYSTEM "alter_session.sgml">
 <!ENTITY alterSubscription  SYSTEM "alter_subscription.sgml">
 <!ENTITY alterSystem        SYSTEM "alter_system.sgml">
 <!ENTITY alterStatistics    SYSTEM "alter_statistics.sgml">
diff --git a/doc/src/sgml/ref/alter_session.sgml b/doc/src/sgml/ref/alter_session.sgml
new file mode 100644
index 0000000000..803d964091
--- /dev/null
+++ b/doc/src/sgml/ref/alter_session.sgml
@@ -0,0 +1,160 @@
+<!--
+doc/src/sgml/ref/alter_session.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="sql-altersession">
+ <indexterm zone="sql-altersystem">
+  <primary>ALTER SESSION</primary>
+ </indexterm>
+
+ <refmeta>
+  <refentrytitle>ALTER SESSION</refentrytitle>
+  <manvolnum>7</manvolnum>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>ALTER SESSION</refname>
+  <refpurpose>change a server configuration parameter of a remote session</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+ALTER SESSION WITH (pid <replaceable class="parameter">session_pid</replaceable>) SET <replaceable
class="parameter">configuration_parameter</replaceable>{ TO | = } { <replaceable class="parameter">value</replaceable>
|'<replaceable class="parameter">value</replaceable>' | DEFAULT } [ [ WITH ] RELOAD ]
 
+
+ALTER SESSION WITH (pid <replaceable class="parameter">session_pid</replaceable>) RESET <replaceable
class="parameter">configuration_parameter</replaceable>[ [ WITH ] RELOAD ]
 
+ALTER SESSION WITH (pid <replaceable class="parameter">session_pid</replaceable>) RESET ALL [ [ WITH ] RELOAD ]
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+  <title>Description</title>
+
+  <para>
+   <command>ALTER SESSION</command> is used for changing server configuration
+   parameters on the specified session. 
+   <command>ALTER SESSION</command> writes the given parameter setting to the
+   file <filename>pg_session_conf/postgresql.<replaceable>beid</replaceable>.conf</filename>
+   file, which is read in addition to <filename>postgresql.conf</filename>
+   and <filename>postgresql.auto.conf</filename>.  Setting a parameter
+   to <literal>DEFAULT</literal>, or using the
+   <command>RESET</command> variant, removes that configuration entry from the
+   session config file. Use <literal>RESET ALL</literal> to remove the
+   parameter file. The session config file lasts until the end of the session.
+  </para>
+
+  <para>
+   Values set with <command>ALTER SESSION</command> will be effective after
+   the next server configuration reload.  A server configuration reload can be
+   commanded by calling the SQL
+   function <function>pg_reload_conf()</function>, running <literal>pg_ctl
+   reload</literal>, sending a <systemitem>SIGHUP</systemitem> signal to the
+   main server process, or specifying <literal>WITH RELOAD</literal>
+   in <command>ALTER SESSION</command>. As <command>ALTER SYSTEM</command>
+   does, <command>ALTER SESSION</command> doesn't override settings changed
+   in-session.
+  </para>
+
+  <para>
+   Only superusers and users who are granted the session user or
+   pg_signal_backend can use <command>ALTER SESSION</command>.  Also, since
+   this command acts directly on the file system and cannot be rolled back, it
+   is not allowed inside a transaction block or function.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>Parameters</title>
+
+  <variablelist>
+   <varlistentry>
+    <term><replaceable class="parameter">session_pid</replaceable></term>
+    <listitem>
+     <para>
+      Process ID of the target session.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">configuration_parameter</replaceable></term>
+    <listitem>
+     <para>
+      Name of a settable configuration parameter.  Available parameters are
+      documented in <xref linkend="runtime-config"/>.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">value</replaceable></term>
+    <listitem>
+     <para>
+      New value of the parameter.  Values can be specified as string
+      constants, identifiers, numbers, or comma-separated lists of
+      these, as appropriate for the particular parameter.
+      <literal>DEFAULT</literal> can be written to specify removing the
+      parameter and its value
+      from <filename>pg_session_conf/postgresql.<replaceable>beid</replaceable>.conf</filename>.
+     </para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
+ </refsect1>
+
+ <refsect1>
+  <title>Notes</title>
+
+  <para>
+   This command can't be used to set <xref linkend="guc-data-directory"/>,
+   parameters that are not allowed in <filename>postgresql.conf</filename>
+   (e.g., <link linkend="runtime-config-preset">preset options</link>), nor
+   parameters that cannot be changed on-session. Only superuser can perform
+   <literal>RESET ALL</literal>.
+  </para>
+
+  <para>
+   See <xref linkend="config-setting"/> for other ways to set the parameters.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>Examples</title>
+
+  <para>
+   Set the <literal>wal_level</literal>:
+<programlisting>
+ALTER SESSION WITH (pid 27162) SET track_functions = pl IMMEDIATE;
+</programlisting>
+  </para>
+
+  <para>
+   Undo that, restoring whatever setting was effective
+   in <filename>postgresql.conf</filename>
+   and <filename>postgresql.auto.conf</filename>:
+<programlisting>
+ALTER SESSION WITH (pid 27162) RESET track_functions IMMEDIATE;
+</programlisting></para>
+ </refsect1>
+
+ <refsect1>
+  <title>Compatibility</title>
+
+  <para>
+   The <command>ALTER SESSION</command> statement is a
+   <productname>PostgreSQL</productname> extension.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>See Also</title>
+
+  <simplelist type="inline">
+   <member><xref linkend="sql-altersystem"/></member>
+   <member><xref linkend="sql-set"/></member>
+   <member><xref linkend="sql-show"/></member>
+  </simplelist>
+ </refsect1>
+
+</refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index db4f4167e3..85f515e2b2 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -62,6 +62,7 @@
    &alterSchema;
    &alterSequence;
    &alterServer;
+   &alterSession;
    &alterStatistics;
    &alterSubscription;
    &alterSystem;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 807393dfaa..7719b475ae 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3923,6 +3923,17 @@ _copyAlterSystemStmt(const AlterSystemStmt *from)
     return newnode;
 }
 
+static AlterSessionStmt *
+_copyAlterSessionStmt(const AlterSessionStmt *from)
+{
+    AlterSessionStmt *newnode = makeNode(AlterSessionStmt);
+
+    COPY_NODE_FIELD(sessionopt);
+    COPY_NODE_FIELD(setstmt);
+    COPY_SCALAR_FIELD(immediate);
+    return newnode;
+}
+
 static CreateSeqStmt *
 _copyCreateSeqStmt(const CreateSeqStmt *from)
 {
@@ -5341,6 +5352,9 @@ copyObjectImpl(const void *from)
         case T_AlterSystemStmt:
             retval = _copyAlterSystemStmt(from);
             break;
+        case T_AlterSessionStmt:
+            retval = _copyAlterSessionStmt(from);
+            break;
         case T_CreateSeqStmt:
             retval = _copyCreateSeqStmt(from);
             break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index a397de155e..b542d060f8 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1732,6 +1732,15 @@ _equalAlterSystemStmt(const AlterSystemStmt *a, const AlterSystemStmt *b)
     return true;
 }
 
+static bool
+_equalAlterSessionStmt(const AlterSessionStmt *a, const AlterSessionStmt *b)
+{
+    COMPARE_NODE_FIELD(sessionopt);
+    COMPARE_NODE_FIELD(setstmt);
+    COMPARE_SCALAR_FIELD(immediate);
+
+    return true;
+}
 
 static bool
 _equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b)
@@ -3406,6 +3415,9 @@ equal(const void *a, const void *b)
         case T_AlterSystemStmt:
             retval = _equalAlterSystemStmt(a, b);
             break;
+        case T_AlterSessionStmt:
+            retval = _equalAlterSessionStmt(a, b);
+            break;
         case T_CreateSeqStmt:
             retval = _equalCreateSeqStmt(a, b);
             break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c1faf4152c..309e6da3ca 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -248,8 +248,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
         AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
         AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
         AlterObjectDependsStmt AlterObjectSchemaStmt AlterOwnerStmt
-        AlterOperatorStmt AlterSeqStmt AlterSystemStmt AlterTableStmt
-        AlterTblSpcStmt AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt
+        AlterOperatorStmt AlterSeqStmt AlterSystemStmt AlterSessionStmt
+        AlterTableStmt AlterTblSpcStmt AlterExtensionStmt
+        AlterExtensionContentsStmt AlterForeignTableStmt
         AlterCompositeTypeStmt AlterUserMappingStmt
         AlterRoleStmt AlterRoleSetStmt AlterPolicyStmt
         AlterDefaultPrivilegesStmt DefACLAction
@@ -303,13 +304,14 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <defelt>    createdb_opt_item copy_opt_item
                 transaction_mode_item
                 create_extension_opt_item alter_extension_opt_item
+                altersess_option_item
 
 %type <ival>    opt_lock lock_type cast_context
 %type <ival>    vacuum_option_list vacuum_option_elem
                 analyze_option_list analyze_option_elem
 %type <boolean>    opt_or_replace
                 opt_grant_grant_option opt_grant_admin_option
-                opt_nowait opt_if_exists opt_with_data
+                opt_nowait opt_if_exists opt_with_data opt_reload
 %type <ival>    opt_nowait_or_skip
 
 %type <list>    OptRoleList AlterOptRoleList
@@ -668,7 +670,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
     QUOTE
 
     RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFERENCING
-    REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA
+    REFRESH REINDEX RELATIVE_P RELEASE RELOAD RENAME REPEATABLE REPLACE REPLICA
     RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP
     ROUTINE ROUTINES ROW ROWS RULE
 
@@ -839,6 +841,7 @@ stmt :
             | AlterPolicyStmt
             | AlterSeqStmt
             | AlterSystemStmt
+            | AlterSessionStmt
             | AlterTableStmt
             | AlterTblSpcStmt
             | AlterCompositeTypeStmt
@@ -10169,6 +10172,45 @@ AlterSystemStmt:
         ;
 
 
+/*****************************************************************************
+ *
+ *        ALTER SESSION
+ *
+ * This is used to change configuration parameters persistently.
+ *****************************************************************************/
+
+AlterSessionStmt:
+            ALTER SESSION WITH '(' altersess_option_item ')' SET generic_set opt_reload
+                {
+                    AlterSessionStmt *n = makeNode(AlterSessionStmt);
+                    n->sessionopt = $5;
+                    n->setstmt = $8;
+                    n->immediate = $9;
+                    $$ = (Node *)n;
+                }
+            | ALTER SESSION WITH '(' altersess_option_item ')' RESET generic_reset opt_reload
+                {
+                    AlterSessionStmt *n = makeNode(AlterSessionStmt);
+                    n->sessionopt = $5;
+                    n->setstmt = $8;
+                    n->immediate = $9;
+                    $$ = (Node *)n;
+                }
+        ;
+
+altersess_option_item:
+        ColLabel Iconst
+        {
+            $$ = makeDefElem($1, (Node *)makeInteger($2), @1);
+        }
+    ;
+
+opt_reload:
+        WITH RELOAD    { $$ = true; }
+        | RELOAD    { $$ = true; }
+        | /*EMPTY*/ { $$ = false; }
+    ;
+
 /*****************************************************************************
  *
  * Manipulate a domain
@@ -15117,6 +15159,7 @@ unreserved_keyword:
             | REINDEX
             | RELATIVE_P
             | RELEASE
+            | RELOAD
             | RENAME
             | REPEATABLE
             | REPLACE
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 3052bbbc21..1a32bb5f52 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -125,6 +125,7 @@
 #include "tcop/tcopprot.h"
 #include "utils/builtins.h"
 #include "utils/datetime.h"
+#include "utils/guc.h"
 #include "utils/memutils.h"
 #include "utils/pidfile.h"
 #include "utils/ps_status.h"
@@ -1242,6 +1243,11 @@ PostmasterMain(int argc, char *argv[])
      */
     RemovePgTempFiles();
 
+    /*
+     * Remove old session configuration files.
+     */
+    CleanupSessionGUCfiles();
+    
     /*
      * Forcibly remove the files signaling a standby promotion request.
      * Otherwise, the existence of those files triggers a promotion too early,
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index def6c03dd0..6631c8498b 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -153,6 +153,9 @@ static const char *excludeDirContents[] =
     /* Contents zeroed on startup, see StartupSUBTRANS(). */
     "pg_subtrans",
 
+    /* Contents removed on startup, see CleanupSessionGUCfiles(). */
+    "pg_session_conf",
+
     /* end of list */
     NULL
 };
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 6ec795f1b4..daa3af725c 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -681,6 +681,11 @@ standard_ProcessUtility(PlannedStmt *pstmt,
             AlterSystemSetConfigFile((AlterSystemStmt *) parsetree);
             break;
 
+        case T_AlterSessionStmt:
+            PreventInTransactionBlock(isTopLevel, "ALTER SESSION");
+            AlterSessionSetConfigFile(pstate, (AlterSessionStmt *) parsetree);
+            break;
+
         case T_VariableSetStmt:
             ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
             break;
@@ -2605,6 +2610,10 @@ CreateCommandTag(Node *parsetree)
             tag = "ALTER SYSTEM";
             break;
 
+        case T_AlterSessionStmt:
+            tag = "ALTER SESSION";
+            break;
+
         case T_VariableSetStmt:
             switch (((VariableSetStmt *) parsetree)->kind)
             {
@@ -3235,6 +3244,10 @@ GetCommandLogLevel(Node *parsetree)
             lev = LOGSTMT_DDL;
             break;
 
+        case T_AlterSessionStmt:
+            lev = LOGSTMT_DDL;
+            break;
+
         case T_VariableSetStmt:
             lev = LOGSTMT_ALL;
             break;
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index c0b6231458..45c005a109 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -703,6 +703,9 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
      */
     before_shmem_exit(ShutdownPostgres, 0);
 
+    /* Session initialization for GUC system */
+    InitializeSessionGUC();
+
     /* The autovacuum launcher is done here */
     if (IsAutoVacuumLauncherProcess())
     {
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index 1c8b5f7d84..dbb131613b 100644
--- a/src/backend/utils/misc/guc-file.l
+++ b/src/backend/utils/misc/guc-file.l
@@ -208,6 +208,29 @@ ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
             ConfFileWithError = PG_AUTOCONF_FILENAME;
             goto bail_out;
         }
+
+        /* load session configuration if any */
+        if (MyBackendId != InvalidBackendId)
+        {
+            /* Use this name for error reporting */
+            static char SessionConfFileName[MAXPGPATH];
+            struct stat st;
+
+            snprintf(SessionConfFileName, sizeof(SessionConfFileName),
+                     PG_SESSIONCONF_FILENAME, MyBackendId);
+
+            /* be silent on absence */
+            if (stat(SessionConfFileName, &st) == 0 &&
+                !ParseConfigFile(SessionConfFileName, true,
+                                 NULL, 0, 0, elevel,
+                                 &head, &tail))
+            {
+                /* Syntax error(s) detected in the file, so bail out */
+                error = true;
+                ConfFileWithError = SessionConfFileName;
+                goto bail_out;
+            }
+        }
     }
     else
     {
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 98d75be292..12cc454537 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -36,6 +36,7 @@
 #include "catalog/namespace.h"
 #include "catalog/pg_authid.h"
 #include "commands/async.h"
+#include "commands/defrem.h"
 #include "commands/prepare.h"
 #include "commands/user.h"
 #include "commands/vacuum.h"
@@ -73,9 +74,11 @@
 #include "storage/dsm_impl.h"
 #include "storage/standby.h"
 #include "storage/fd.h"
+#include "storage/ipc.h"
 #include "storage/large_object.h"
 #include "storage/pg_shmem.h"
 #include "storage/proc.h"
+#include "storage/procarray.h"
 #include "storage/predicate.h"
 #include "tcop/tcopprot.h"
 #include "tsearch/ts_cache.h"
@@ -4483,7 +4486,8 @@ static void ShowAllGUCConfig(DestReceiver *dest);
 static char *_ShowOption(struct config_generic *record, bool use_units);
 static bool validate_option_array_item(const char *name, const char *value,
                            bool skipIfNoPermissions);
-static void write_auto_conf_file(int fd, const char *filename, ConfigVariable *head_p);
+static void write_auto_conf_file(int fd, const char *filename, bool is_session,
+                                 ConfigVariable *head_p);
 static void replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
                           const char *name, const char *value);
 
@@ -4975,6 +4979,62 @@ guc_name_compare(const char *namea, const char *nameb)
     return 0;
 }
 
+void
+CleanupSessionGUCfiles(void)
+{
+    DIR           *dir;
+    struct dirent *entry;
+    char        fname[MAXPGPATH];
+
+    dir = AllocateDir(PG_SESSIONCONF_DIRNAME);
+    while ((entry = ReadDir(dir, PG_SESSIONCONF_DIRNAME)) != NULL)
+    {
+        if (strcmp(entry->d_name, ".") == 0 ||
+            strcmp(entry->d_name, "..") == 0)
+            continue;
+
+        snprintf(fname, sizeof(fname), "%s/%s", PG_SESSIONCONF_DIRNAME,
+                 entry->d_name);
+
+        /*
+         * no need for durable_unlnk here since this is done again in the next
+         * startup after a crash
+         */
+        if (unlink(fname) != 0)
+            ereport(NOTICE,
+                    (errcode_for_file_access(),
+                     errmsg("could not remove file \"%s\" during clean up of session config files: %m",
+                            fname)));
+    }
+    FreeDir(dir);
+}
+
+static void
+RemoveSessionGUCFile(int code, Datum arg)
+{
+    char SessionConfFileName[MAXPGPATH];
+    int     beid = DatumGetInt32(arg);
+
+    if (beid != InvalidBackendId)
+    {
+        LWLockAcquire(AutoFileLock, LW_EXCLUSIVE);
+        snprintf(SessionConfFileName, sizeof(SessionConfFileName),
+                 PG_SESSIONCONF_FILENAME, beid);
+        unlink(SessionConfFileName);
+        LWLockRelease(AutoFileLock);
+    }
+}
+
+void
+InitializeSessionGUC(void)
+{
+    if (!IsUnderPostmaster || MyBackendId == InvalidBackendId)
+        return;
+
+    RemoveSessionGUCFile(0, 0);
+    on_shmem_exit(RemoveSessionGUCFile, Int32GetDatum(MyBackendId));
+}
+
 
 /*
  * Initialize GUC options during program startup.
@@ -7471,16 +7531,19 @@ flatten_set_variable_args(const char *name, List *args)
  * values before writing them.
  */
 static void
-write_auto_conf_file(int fd, const char *filename, ConfigVariable *head)
+write_auto_conf_file(int fd, const char *filename, bool is_session,
+                     ConfigVariable *head)
 {
     StringInfoData buf;
     ConfigVariable *item;
+    char *command_name = is_session ? "ALTER SESSION" : "ALTER_SYSTEM";
 
     initStringInfo(&buf);
 
     /* Emit file header containing warning comment */
     appendStringInfoString(&buf, "# Do not edit this file manually!\n");
-    appendStringInfoString(&buf, "# It will be overwritten by the ALTER SYSTEM command.\n");
+    appendStringInfo(&buf, "# It will be overwritten by the %s command.\n",
+        command_name);
 
     errno = 0;
     if (write(fd, buf.data, buf.len) != buf.len)
@@ -7600,103 +7663,91 @@ replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
 
 
 /*
- * Execute ALTER SYSTEM statement.
- *
- * Read the old PG_AUTOCONF_FILENAME file, merge in the new variable value,
- * and write out an updated file.  If the command is ALTER SYSTEM RESET ALL,
- * we can skip reading the old file and just write an empty file.
- *
- * An LWLock is used to serialize updates of the configuration file.
- *
- * In case of an error, we leave the original automatic
- * configuration file (PG_AUTOCONF_FILENAME) intact.
+  Check and process the given set statment of ALTER SYSTEM and ALTER SESSION.
  */
-void
-AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
+static void
+AlterConfigProcessSetCommand(VariableSetStmt *setstmt,
+                             bool is_session, bool is_superuser,
+                             char **name, char **value, bool *resetall)
 {
-    char       *name;
-    char       *value;
-    bool        resetall = false;
-    ConfigVariable *head = NULL;
-    ConfigVariable *tail = NULL;
-    volatile int Tmpfd;
-    char        AutoConfFileName[MAXPGPATH];
-    char        AutoConfTmpFileName[MAXPGPATH];
+    *name = setstmt->name;
 
-    if (!superuser())
-        ereport(ERROR,
-                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                 (errmsg("must be superuser to execute ALTER SYSTEM command"))));
-
-    /*
-     * Extract statement arguments
-     */
-    name = altersysstmt->setstmt->name;
-
-    switch (altersysstmt->setstmt->kind)
+    switch (setstmt->kind)
     {
         case VAR_SET_VALUE:
-            value = ExtractSetVariableArgs(altersysstmt->setstmt);
+            *value = ExtractSetVariableArgs(setstmt);
             break;
 
         case VAR_SET_DEFAULT:
         case VAR_RESET:
-            value = NULL;
+            *value = NULL;
             break;
 
         case VAR_RESET_ALL:
-            value = NULL;
-            resetall = true;
+            *value = NULL;
+            *resetall = true;
             break;
 
         default:
-            elog(ERROR, "unrecognized alter system stmt type: %d",
-                 altersysstmt->setstmt->kind);
+            elog(ERROR, "unrecognized set type: %d",
+                 setstmt->kind);
             break;
     }
 
     /*
      * Unless it's RESET_ALL, validate the target variable and value
      */
-    if (!resetall)
+    if (!*resetall)
     {
         struct config_generic *record;
 
-        record = find_option(name, false, ERROR);
+        record = find_option(*name, false, ERROR);
         if (record == NULL)
             ereport(ERROR,
                     (errcode(ERRCODE_UNDEFINED_OBJECT),
                      errmsg("unrecognized configuration parameter \"%s\"",
-                            name)));
+                            *name)));
 
         /*
          * Don't allow parameters that can't be set in configuration files to
          * be set in PG_AUTOCONF_FILENAME file.
          */
-        if ((record->context == PGC_INTERNAL) ||
+
+        /* PG_SUSET is changebale but only by superusers  */
+        if (is_session && !is_superuser && record->context == PGC_SUSET)
+                ereport(ERROR,
+                        (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                         errmsg("permission denied to set parameter \"%s\"",
+                                *name)));
+
+        /* ALTER SESSION allows only parameters changeabe on-session */
+        if ((is_session &&
+             (record->context != PGC_USERSET &&
+              record->context != PGC_SUSET)) ||
+            record->context == PGC_INTERNAL ||
             (record->flags & GUC_DISALLOW_IN_FILE) ||
             (record->flags & GUC_DISALLOW_IN_AUTO_FILE))
             ereport(ERROR,
                     (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
                      errmsg("parameter \"%s\" cannot be changed",
-                            name)));
+                            *name)));
 
         /*
          * If a value is specified, verify that it's sane.
          */
-        if (value)
+        if (*value)
         {
             union config_var_val newval;
             void       *newextra = NULL;
 
             /* Check that it's acceptable for the indicated parameter */
-            if (!parse_and_validate_value(record, name, value,
+            if (!parse_and_validate_value(record, *name, *value,
                                           PGC_S_FILE, ERROR,
                                           &newval, &newextra))
                 ereport(ERROR,
                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                          errmsg("invalid value for parameter \"%s\": \"%s\"",
-                                name, value)));
+                                *name, *value)));
 
             if (record->vartype == PGC_STRING && newval.stringval != NULL)
                 free(newval.stringval);
@@ -7708,23 +7759,30 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
              * grammar for config files doesn't support embedded newlines in
              * string literals.
              */
-            if (strchr(value, '\n'))
+            if (strchr(*value, '\n'))
                 ereport(ERROR,
                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                         errmsg("parameter value for ALTER SYSTEM must not contain a newline")));
+                         errmsg("parameter value for SET must not contain a newline")));
         }
     }
+}
 
-    /*
-     * PG_AUTOCONF_FILENAME and its corresponding temporary file are always in
-     * the data directory, so we can reference them by simple relative paths.
-     */
-    snprintf(AutoConfFileName, sizeof(AutoConfFileName), "%s",
-             PG_AUTOCONF_FILENAME);
-    snprintf(AutoConfTmpFileName, sizeof(AutoConfTmpFileName), "%s.%s",
-             AutoConfFileName,
-             "tmp");
+/*
+ * Edit or create auto configuration files.
+ */
+static void
+EditAutoConfigFile(char *confname, bool is_session,
+                   char *name, char *value, bool resetall)
+{
+    struct stat st;
+    char    tmpname[MAXPGPATH];
+    volatile int Tmpfd;
+    ConfigVariable *head = NULL;
+    ConfigVariable *tail = NULL;
 
+    /* We create a temporary file then rename it to the persistent name */
+    snprintf(tmpname, sizeof(tmpname), "%s.%s", confname, "tmp");
+    
     /*
      * Only one backend is allowed to operate on PG_AUTOCONF_FILENAME at a
      * time.  Use AutoFileLock to ensure that.  We must hold the lock while
@@ -7734,30 +7792,43 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
 
     /*
      * If we're going to reset everything, then no need to open or parse the
-     * old file.  We'll just write out an empty list.
+     * old file.
+     */
+    if (is_session && resetall)
+    {
+        /* RESET ALL just remove files for session configuratrion */
+        if (stat(confname, &st) == 0)
+            durable_unlink(confname, ERROR);
+
+        unlink(tmpname);    /* ignore error */
+        LWLockRelease(AutoFileLock);
+        return;
+    }
+
+    /*
+     * We'll just write out an empty list for auto configration for RESET
+     * ALL
      */
     if (!resetall)
     {
-        struct stat st;
-
-        if (stat(AutoConfFileName, &st) == 0)
+        if (stat(confname, &st) == 0)
         {
-            /* open old file PG_AUTOCONF_FILENAME */
+            /* open old auto config file  */
             FILE       *infile;
 
-            infile = AllocateFile(AutoConfFileName, "r");
+            infile = AllocateFile(confname, "r");
             if (infile == NULL)
                 ereport(ERROR,
                         (errcode_for_file_access(),
                          errmsg("could not open file \"%s\": %m",
-                                AutoConfFileName)));
+                                confname)));
 
             /* parse it */
-            if (!ParseConfigFp(infile, AutoConfFileName, 0, LOG, &head, &tail))
+            if (!ParseConfigFp(infile, confname, 0, LOG, &head, &tail))
                 ereport(ERROR,
                         (errcode(ERRCODE_CONFIG_FILE_ERROR),
                          errmsg("could not parse contents of file \"%s\"",
-                                AutoConfFileName)));
+                                confname)));
 
             FreeFile(infile);
         }
@@ -7776,13 +7847,13 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
      * If there is a temp file left over due to a previous crash, it's okay to
      * truncate and reuse it.
      */
-    Tmpfd = BasicOpenFile(AutoConfTmpFileName,
+    Tmpfd = BasicOpenFile(tmpname,
                           O_CREAT | O_RDWR | O_TRUNC);
     if (Tmpfd < 0)
         ereport(ERROR,
                 (errcode_for_file_access(),
                  errmsg("could not open file \"%s\": %m",
-                        AutoConfTmpFileName)));
+                        tmpname)));
 
     /*
      * Use a TRY block to clean up the file if we fail.  Since we need a TRY
@@ -7791,7 +7862,7 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
     PG_TRY();
     {
         /* Write and sync the new contents to the temporary file */
-        write_auto_conf_file(Tmpfd, AutoConfTmpFileName, head);
+        write_auto_conf_file(Tmpfd, tmpname, is_session, head);
 
         /* Close before renaming; may be required on some platforms */
         close(Tmpfd);
@@ -7802,7 +7873,7 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
          * at worst it can lose the parameters set by last ALTER SYSTEM
          * command.
          */
-        durable_rename(AutoConfTmpFileName, AutoConfFileName, ERROR);
+        durable_rename(tmpname, confname, ERROR);
     }
     PG_CATCH();
     {
@@ -7811,7 +7882,7 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
             close(Tmpfd);
 
         /* Unlink, but ignore any error */
-        (void) unlink(AutoConfTmpFileName);
+        (void) unlink(tmpname);
 
         PG_RE_THROW();
     }
@@ -7822,6 +7893,138 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
     LWLockRelease(AutoFileLock);
 }
 
+/*
+ * Execute ALTER SYSTEM statement.
+ *
+ * Read the old PG_AUTOCONF_FILENAME file, merge in the new variable value,
+ * and write out an updated file.  If the command is ALTER SYSTEM RESET ALL,
+ * we can skip reading the old file and just write an empty file.
+ *
+ * An LWLock is used to serialize updates of the configuration file.
+ *
+ * In case of an error, we leave the original automatic
+ * configuration file (PG_AUTOCONF_FILENAME) intact.
+ */
+void
+AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
+{
+    char       *name;
+    char       *value;
+    bool        resetall = false;
+    char        AutoConfFileName[MAXPGPATH];
+
+    if (!superuser())
+        ereport(ERROR,
+                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                 (errmsg("must be superuser to execute ALTER SYSTEM command"))));
+
+    /*
+     * Extract statement arguments
+     */
+
+    AlterConfigProcessSetCommand(altersysstmt->setstmt, false, false,
+                                 &name, &value, &resetall);
+    /*
+     * PG_AUTOCONF_FILENAME and its corresponding temporary file are always in
+     * the data directory, so we can reference them by simple relative paths.
+     */
+    snprintf(AutoConfFileName, sizeof(AutoConfFileName), "%s",
+             PG_AUTOCONF_FILENAME);
+
+    EditAutoConfigFile(AutoConfFileName, false, name, value, resetall);
+}
+
+/*
+ * Execute ALTER SESSION statement.
+ *
+ * Peforms the similar thing with ALTER SYSTEM to PG_SESSIONCONF_FILENAME.
+ */
+void
+AlterSessionSetConfigFile(ParseState *pstate, AlterSessionStmt *altersesstmt)
+{
+    int            target_pid;
+    PGPROC       *target_proc;
+    BackendId    target_beid;
+    DefElem       *def;
+    char       *name;
+    char       *value;
+    bool        resetall = false;
+    char        SessionConfigFile[MAXPGPATH];
+
+    def = altersesstmt->sessionopt;
+
+    /* ignoring namespace */
+    if (strcmp(def->defname, "pid") != 0)
+        ereport(ERROR,
+                (errmsg ("only pid is allowed here"),
+                 parser_errposition(pstate, def->location)));
+
+    target_pid = defGetInt32(def);
+
+    target_proc = BackendPidGetProc(target_pid);
+
+    if (target_proc == NULL)
+        ereport(ERROR,
+                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                 errmsg("PID %d is not a PostgreSQL server process",
+                        target_pid)));
+
+    target_beid = target_proc->backendId;
+
+    /* The same condition to pg_signal_backend() */
+    if ((superuser_arg(target_proc->roleId) && !superuser()) ||
+        (!has_privs_of_role(GetUserId(), target_proc->roleId) &&
+         !has_privs_of_role(GetUserId(), DEFAULT_ROLE_SIGNAL_BACKENDID)))
+        ereport(ERROR,
+                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                 errmsg("insufficient privileges for the session")));
+
+    if (target_beid == InvalidBackendId)
+        elog(ERROR, "not a backend");
+
+    AlterConfigProcessSetCommand(altersesstmt->setstmt, true, superuser(),
+                                 &name, &value, &resetall);
+
+    /* don't allow RESET ALL for non-superusers */
+    if (resetall && !superuser())
+        ereport(ERROR,
+                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                 errmsg("RESET ALL requres superuser privileges")));
+
+    /* Ok, edit or create session config file */
+    snprintf(SessionConfigFile, sizeof(SessionConfigFile),
+             PG_SESSIONCONF_FILENAME, target_beid);
+
+    EditAutoConfigFile(SessionConfigFile, true, name, value, resetall);
+
+    /*
+     * Some racy condition here.
+     *
+     * The session config file has been created or changed. Now check again if
+     * the target session is still living. A pid is supposed not to be
+     * assigned to another process shortly but check backend ID just in
+     * case. Still it's possible that the both match with a different
+     * session. In the case the config file has been removed by the
+     * session-end after editing, or recreated after the removal. Even in the
+     * latter case the new session receives the change commanded this time,
+     * which doesn't harm so much.
+     */
+    if (target_proc->pid != target_pid || target_proc->backendId != target_beid)
+    {
+        RemoveSessionGUCFile(0, Int32GetDatum(target_beid));
+        ereport(WARNING,
+                (errmsg ("target session has terminated")));
+        return;
+    }
+    
+    if (altersesstmt->immediate)
+    {
+        if (kill(target_pid, SIGHUP))
+            ereport(WARNING,
+                    (errmsg("failed to send signal to session: %m")));
+    }
+}
+
 /*
  * SET command
  */
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index fd50a809ea..138190e9dc 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -221,7 +221,8 @@ static const char *const subdirs[] = {
     "pg_xact",
     "pg_logical",
     "pg_logical/snapshots",
-    "pg_logical/mappings"
+    "pg_logical/mappings",
+    "pg_session_conf"
 };
 
 
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index fbe2dc14a7..74e4fe2f0d 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -407,6 +407,7 @@ typedef enum NodeTag
     T_RefreshMatViewStmt,
     T_ReplicaIdentityStmt,
     T_AlterSystemStmt,
+    T_AlterSessionStmt,
     T_CreatePolicyStmt,
     T_AlterPolicyStmt,
     T_CreateTransformStmt,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 4ec8a83541..98658ce714 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -3121,6 +3121,18 @@ typedef struct AlterSystemStmt
     VariableSetStmt *setstmt;    /* SET subcommand */
 } AlterSystemStmt;
 
+/* ----------------------
+ *        Alter Session Statement
+ * ----------------------
+ */
+typedef struct AlterSessionStmt
+{
+    NodeTag        type;
+    DefElem       *sessionopt;        /* session property */
+    VariableSetStmt *setstmt;    /* SET subcommand */
+    bool        immediate;        /* reload immediately */
+} AlterSessionStmt;
+
 /* ----------------------
  *        Cluster Statement (support pbrown's cluster index implementation)
  * ----------------------
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index adeb834ce8..aaae750c3f 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -330,6 +330,7 @@ PG_KEYWORD("refresh", REFRESH, UNRESERVED_KEYWORD)
 PG_KEYWORD("reindex", REINDEX, UNRESERVED_KEYWORD)
 PG_KEYWORD("relative", RELATIVE_P, UNRESERVED_KEYWORD)
 PG_KEYWORD("release", RELEASE, UNRESERVED_KEYWORD)
+PG_KEYWORD("reload", RELOAD, UNRESERVED_KEYWORD)
 PG_KEYWORD("rename", RENAME, UNRESERVED_KEYWORD)
 PG_KEYWORD("repeatable", REPEATABLE, UNRESERVED_KEYWORD)
 PG_KEYWORD("replace", REPLACE, UNRESERVED_KEYWORD)
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index c07e7b945e..e02b8908c8 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -14,6 +14,7 @@
 #define GUC_H
 
 #include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
 #include "tcop/dest.h"
 #include "utils/array.h"
 
@@ -33,6 +34,14 @@
  */
 #define PG_AUTOCONF_FILENAME        "postgresql.auto.conf"
 
+/*
+ * Session configuration file name for ALTER SESSION.
+ * This file will be used to store values of configuration parameters
+ * set by ALTER SESSION command.
+ */
+#define PG_SESSIONCONF_DIRNAME    "pg_session_conf"
+#define PG_SESSIONCONF_FILENAME    PG_SESSIONCONF_DIRNAME"/postgresql.%d.conf"
+
 /*
  * Certain options can only be set at certain times. The rules are
  * like this:
@@ -351,6 +360,8 @@ extern const char *GetConfigOption(const char *name, bool missing_ok,
 extern const char *GetConfigOptionResetString(const char *name);
 extern int    GetConfigOptionFlags(const char *name, bool missing_ok);
 extern void ProcessConfigFile(GucContext context);
+extern void CleanupSessionGUCfiles(void);
+extern void InitializeSessionGUC(void);
 extern void InitializeGUCOptions(void);
 extern bool SelectConfigFiles(const char *userDoption, const char *progname);
 extern void ResetAllOptions(void);
@@ -367,6 +378,8 @@ extern int set_config_option(const char *name, const char *value,
                   GucAction action, bool changeVal, int elevel,
                   bool is_reload);
 extern void AlterSystemSetConfigFile(AlterSystemStmt *setstmt);
+extern void AlterSessionSetConfigFile(ParseState *pstate,
+                                      AlterSessionStmt *altersesstmt);
 extern char *GetConfigOptionByName(const char *name, const char **varname,
                       bool missing_ok);
 extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow);
-- 
2.16.3


В списке pgsql-hackers по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: Early WIP/PoC for inlining CTEs
Следующее
От: "Imai, Yoshikazu"
Дата:
Сообщение: RE: speeding up planning with partitions