Feature: allow to route queries to a specific backend node for a specific user connec...
authorBo Peng <pengbo@sraoss.co.jp>
Tue, 13 Jun 2023 05:56:29 +0000 (14:56 +0900)
committerBo Peng <pengbo@sraoss.co.jp>
Tue, 13 Jun 2023 05:56:29 +0000 (14:56 +0900)
This commit adds a new parameter "user_redirect_preference_list" to
allow to send SELECT queries to a specific backend node for a
specific user connection.

doc.ja/src/sgml/loadbalance.sgml
doc/src/sgml/loadbalance.sgml
src/config/pool_config_variables.c
src/include/pool_config.h
src/protocol/pool_pg_utils.c
src/sample/pgpool.conf.sample-stream
src/test/regression/tests/008.dbredirect/select.pgbench
src/test/regression/tests/008.dbredirect/select1.pgbench
src/test/regression/tests/008.dbredirect/test.sh
src/utils/pool_process_reporting.c

index 75ad5166ed6f821e4934660edd8792ae50eb1f98..08a85c5a2416b4a3e2caf64f33adae3a47ac5ac8 100644 (file)
@@ -949,6 +949,120 @@ primary_routing_query_pattern_list = 'SELECT \* FROM table_name1\;;SELECT col1,
     </listitem>
    </varlistentry>
 
+   <varlistentry id="guc-user-redirect-preference-list" xreflabel="user_redirect_preference_list">
+    <term><varname>user_redirect_preference_list</varname> (<type>string</type>)
+     <indexterm>
+      <!--
+      <primary><varname>user_redirect_preference_list</varname> configuration parameter</primary>
+      -->
+      <primary><varname>user_redirect_preference_list</varname> 設定パラメータ</primary>
+     </indexterm>
+    </term>
+    <listitem>
+     <para>
+      <!--
+      Specifies the list of <replaceable>"user-name:node id(ratio)"</replaceable> pairs
+      to send <acronym>SELECT</acronym> queries to a particular backend
+      node for a particular user connection at a specified load balance ratio.
+      The load balance ratio specifies a value between 0 and 1. The default is 1.0.
+      -->
+      特定のユーザの接続で<acronym>SELECT</acronym>クエリが指定したロードバランス比率で特定のバックエンドノードに送信されるように、"<replaceable>ユーザ名:ノードID(比率)</replaceable>"ペアのリストを指定します。ロードバランス比率は0-1の間の値を指定します。
+      比率の指定を省略した場合は、デフォルトの1.0となります。
+     </para>
+     <para>
+      <!--
+      For example, by specifying "user1:1(0.5)", <productname>Pgpool-II</productname>
+      will redirect 50% <acronym>SELECT</acronym> queries to the backend node of ID 1 for
+      the connection of user <literal>user1</literal>.
+      -->
+      たとえば"user1:1(0.5)"とした場合、<literal>user1</literal>ユーザからの接続においては、<productname>Pgpool-II</productname>は50%の<acronym>SELECT</acronym>クエリをIDが1のバックエンドノードに送信します。
+     </para>
+     <para>
+      <!--
+      You can specify multiple <replaceable>"user-name:node id"</replaceable> pairs
+      by separating them using comma (,).
+      -->
+      複数の"<replaceable>ユーザ名:ノードID(比率)</replaceable>"のペアをカンマ(,)で区切って指定することができます。
+     </para>
+     <para>
+      <!--
+      Regular expressions are also accepted for user name.
+      You can use special keywords as <replaceable>node id</replaceable>.
+      If <emphasis>"primary"</emphasis> is specified, queries are sent to the primary node, and
+      if <emphasis>"standby"</emphasis> is specified, one of the standby nodes are selected randomly
+      based on weights (<xref linkend="guc-backend-weight">).
+      -->
+      ユーザ名には正規表現を指定することができます。
+      <replaceable>ノードID</replaceable>には特別なキーワードを使うことができます。
+      "<emphasis>primary</emphasis>"が指定された場合にはクエリはプライマリノードに送られます。
+      また、"<emphasis>standby</emphasis>"が指定された場合はスタンバイノードのうちどれかをロードバランス比率に応じてランダムに選択します。
+     </para>
+
+     <example id="example-user-redirect-list">
+      <!--
+      <title>Using user_redirect_preference_list</title>
+      -->
+      <title>user_redirect_preference_listの利用</title>
+      <para>
+       <!--
+       If you want to configure the following <acronym>SELECT</acronym> query routing rules:
+       -->
+       <acronym>SELECT</acronym>クエリのルーティングルールを以下のように設定したい場合:
+      </para>
+
+      <itemizedlist>
+       <listitem>
+        <para>
+         <!--
+         Route all <acronym>SELECT</acronym> queries from the connections
+         using user <literal>postgres</literal> to the primary backend node.
+         -->
+         全ての<literal>postgres</literal>ユーザからの<acronym>SELECT</acronym>クエリはプライマリバックエンドノードに送る。
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+         <!--
+         Route 30% <acronym>SELECT</acronym> queries from the connections
+         using user <literal>user0</literal> or <literal>user1</literal>
+         to backend node of ID 1.
+         The other 70% <acronym>SELECT</acronym> queries will be sent to other backend nodes.
+         -->
+         <literal>user0</literal>または<literal>user1</literal>ユーザからの30%の<acronym>SELECT</acronym>クエリはIDが1のバックエンドノードに送る。
+         残りの70%のSELECTクエリは他のバックエンドノードに送る。
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+         <!--
+         Route all <acronym>SELECT</acronym> queries from the connections
+         using user <literal>user2</literal> to standby backend nodes.
+         -->
+         全ての<literal>user2</literal>ユーザからの<acronym>SELECT</acronym>クエリはスタンバイバックエンドノードに送る。
+        </para>
+       </listitem>
+
+      </itemizedlist>
+      <para>
+       <!--
+       then the <xref linkend="guc-user-redirect-preference-list"> will be configured as follows:
+       -->
+       <xref linkend="guc-user-redirect-preference-list">は以下のように設定します。
+       <programlisting>
+user_redirect_preference_list = 'postgres:primary,user[01]:1(0.3),user2:standby'
+       </programlisting>
+      </para>
+     </example>
+
+     <para>
+      <!--
+      This parameter can be changed by reloading the <productname>Pgpool-II</> configurations.
+      -->
+      このパラメータは<productname>Pgpool-II</>の設定を再読み込みすることで変更可能です。
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry id="guc-database-redirect-preference-list" xreflabel="database_redirect_preference_list">
     <term><varname>database_redirect_preference_list</varname> (<type>string</type>)
      <indexterm>
@@ -964,6 +1078,7 @@ primary_routing_query_pattern_list = 'SELECT \* FROM table_name1\;;SELECT col1,
       Specifies the list of <replaceable>"database-name:node id"</replaceable> pairs
       to send <acronym>SELECT</acronym> queries to a particular backend
       node for a particular database connection.
+      The load balance ratio specifies a value between 0 and 1. The default is 1.0.
       -->
       特定のデータベース接続で<acronym>SELECT</acronym>クエリが指定したロードバランス比率で特定のバックエンドノードに送信されるように、"<replaceable>データベース名:ノードID(比率)</replaceable>"ペアのリストを指定します。ロードバランス比率は0-1の間の値を指定します。
       比率の指定を省略した場合は、デフォルトの1.0となります。
@@ -972,12 +1087,16 @@ primary_routing_query_pattern_list = 'SELECT \* FROM table_name1\;;SELECT col1,
       <!--
       For example, by specifying "test:1", <productname>Pgpool-II</productname>
       will redirect all <acronym>SELECT</acronym> queries to the backend node of ID 1 for
-      the connection to "test" database.
+      the connection to <literal>test</literal> database.
+      -->
+      たとえば"test:1(0.5)"とした場合、<literal>test</literal>データベースへの接続においては、<productname>Pgpool-II</productname>は50%の<acronym>SELECT</acronym>クエリをIDが1のバックエンドノードに送信します。
+     </para>
+     <para>
+      <!--
       You can specify multiple <replaceable>"database name:node id"</replaceable> pair by separating them
       using comma (,).
       -->
-      たとえば"test:1(0.5)"とした場合、"test"データベースへの接続においては、<productname>Pgpool-II</productname>は50%の<acronym>SELECT</acronym>クエリをIDが1のバックエンドノードに送信します。
-      複数の"<replaceable>データベース名:ノードID</replaceable>"のペアを カンマ(,)で区切って指定することができます。
+      複数の"<replaceable>データベース名:ノードID(比率)</replaceable>"のペアをカンマ(,)で区切って指定することができます。
      </para>
      <para>
       <!--
@@ -990,7 +1109,7 @@ primary_routing_query_pattern_list = 'SELECT \* FROM table_name1\;;SELECT col1,
       データベース名には正規表現を指定することができます。
       <replaceable>ノードID</replaceable>には特別なキーワードを使うことができます。
       "<emphasis>primary</emphasis>"が指定された場合にはクエリはプライマリノードに送られます。
-      ã\81¾ã\81\9fã\80\81"<emphasis>standby</emphasis>"ã\81\8cæ\8c\87å®\9aã\81\95ã\82\8cã\81\9få ´å\90\88ã\81¯ã\82¹ã\82¿ã\83³ã\83\90ã\82¤ã\83\8eã\83¼ã\83\89ã\81®ã\81\86ã\81¡ã\81©ã\82\8cã\81\8bã\82\92ã\82¦ã\82§ã\82¤ã\83\88(<xref linkend="guc-backend-weight">)に応じてランダムに選択します。
+      ã\81¾ã\81\9fã\80\81"<emphasis>standby</emphasis>"ã\81\8cæ\8c\87å®\9aã\81\95ã\82\8cã\81\9få ´å\90\88ã\81¯ã\82¹ã\82¿ã\83³ã\83\90ã\82¤ã\83\8eã\83¼ã\83\89ã\81®ã\81\86ã\81¡ã\81©ã\82\8cã\81\8bã\82\92ã\83­ã\83¼ã\83\89ã\83\90ã\83©ã\83³ã\82¹æ¯\94ç\8e\87に応じてランダムに選択します。
      </para>
 
      <example id="example-database-redirect-list">
@@ -1007,31 +1126,33 @@ primary_routing_query_pattern_list = 'SELECT \* FROM table_name1\;;SELECT col1,
 
       <itemizedlist>
        <listitem>
-       <para>
-        <!--
-        Route all <acronym>SELECT</acronym> queries on <literal>postgres</literal>
-        database to the primary backend node.
-        -->
-        全ての<literal>postgres</literal>データベースにおける<acronym>SELECT</acronym>クエリはプライマリバックエンドノードに送る。
-       </para>
+        <para>
+         <!--
+         Route all <acronym>SELECT</acronym> queries on <literal>postgres</literal>
+         database to the primary backend node.
+         -->
+         全ての<literal>postgres</literal>データベースにおける<acronym>SELECT</acronym>クエリはプライマリバックエンドノードに送る。
+        </para>
        </listitem>
        <listitem>
-       <para>
-        <!--
-        Route all <acronym>SELECT</acronym> queries on <literal>mydb0</literal> or on
-        <literal>mydb1</literal> databases to backend node of ID 1.
-        -->
-        全ての<literal>mydb0</literal>または<literal>mydb1</literal>データベースにおける30%の<acronym>SELECT</acronym>クエリはIDが1のバックエンドノードに送る。
-       </para>
+        <para>
+         <!--
+         Route 30% <acronym>SELECT</acronym> queries on <literal>mydb0</literal> or on
+         <literal>mydb1</literal> databases to backend node of ID 1.
+         The other 70% <acronym>SELECT</acronym> queries will be sent to other backend nodes.
+         -->
+         <literal>mydb0</literal>または<literal>mydb1</literal>データベースにおける30%の<acronym>SELECT</acronym>クエリはIDが1のバックエンドノードに送る。
+         残りの70%のSELECTクエリは他のバックエンドノードに送る。
+        </para>
        </listitem>
        <listitem>
-       <para>
-        <!--
-        Route all <acronym>SELECT</acronym> queries on <literal>mydb2</literal>
-        database to standby backend nodes.
-        -->
-        全ての<literal>mydb2</literal>データベースにおける<acronym>SELECT</acronym>クエリはスタンバイバックエンドノードに送る。
-       </para>
+        <para>
+         <!--
+         Route all <acronym>SELECT</acronym> queries on <literal>mydb2</literal>
+         database to standby backend nodes.
+         -->
+         全ての<literal>mydb2</literal>データベースにおける<acronym>SELECT</acronym>クエリはスタンバイバックエンドノードに送る。
+        </para>
        </listitem>
 
       </itemizedlist>
@@ -1068,11 +1189,17 @@ database_redirect_preference_list = 'postgres:primary,mydb[01]:1(0.3),mydb2:stan
 
      <para>
       <!--
-      Specifies the list of <replaceable>"application-name:node id"</replaceable> pairs
+      Specifies the list of <replaceable>"application-name:node id(ratio)"</replaceable> pairs
       to send <acronym>SELECT</acronym> queries to a particular backend
-      node for a particular client application connection.
+      node for a particular client application connection at a specified load balance ratio.
+      The load balance ratio specifies a value between 0 and 1. The default is 1.0.
+      You can specify multiple <replaceable>"application-name:node id(ratio)"</replaceable> pairs
+      by separating them using comma (,).
       -->
       特定のクライアントアプリケーションの接続で<acronym>SELECT</acronym>クエリが指定したロードバランス比率で特定のバックエンドノードに送信されるように、"<replaceable>アプリケーション名:ノードID(比率)</replaceable>"ペアのリストを指定します。
+      ロードバランス比率は0-1の間の値を指定します。
+      比率の指定を省略した場合は、デフォルトの1.0となります。
+      複数の"<replaceable>アプリケーション名:ノードID(比率)</replaceable>"のペアを カンマ(,)で区切って指定することができます。
      </para>
 
      <note>
@@ -1109,15 +1236,16 @@ database_redirect_preference_list = 'postgres:primary,mydb[01]:1(0.3),mydb2:stan
 
      <para>
       <!--
-      The notion of <xref linkend="guc-app-name-redirect-preference-list">
-      is same as the <xref linkend="guc-database-redirect-preference-list">
-      thus you can also use the regular expressions for application names.
-      Similarly special keyword <emphasis>"primary"</emphasis> indicates the primary node and
-      <emphasis>"standby"</emphasis> indicates one of standby nodes.
+      Regular expressions are also accepted for application name.
+      You can use special keywords as <replaceable>node id</replaceable>.
+      If <emphasis>"primary"</emphasis> is specified, queries are sent to the primary node, and
+      if <emphasis>"standby"</emphasis> is specified, one of the standby nodes are selected randomly
+      based on weights.
       -->
-      <xref linkend="guc-app-name-redirect-preference-list">の記法は<xref linkend="guc-database-redirect-preference-list">と同じですので、アプリケーション名には正規表現も使用できます。
-       同様に特別なキーワード"<emphasis>primary</emphasis>"はプライマリノードを、"<emphasis>standby</emphasis>"はスタンバイサーバのいずれかを意味します。
-       ロードバランス比率は0-1の間の値を指定します。ロードバランス比率の指定を省略した場合は、デフォルトの1.0となります。
+      アプリケーション名には正規表現を指定することができます。
+      <replaceable>ノードID</replaceable>には特別なキーワードを使うことができます。
+      "<emphasis>primary</emphasis>"が指定された場合にはクエリはプライマリノードに送られます。
+      また、"<emphasis>standby</emphasis>"が指定された場合はスタンバイノードのうちどれかをロードバランス比率に応じてランダムに選択します。
      </para>
 
      <example id="example-app-name-redirect-list">
@@ -1145,10 +1273,11 @@ database_redirect_preference_list = 'postgres:primary,mydb[01]:1(0.3),mydb2:stan
        <listitem>
        <para>
         <!--
-        Route all <acronym>SELECT</acronym> queries from <literal>myapp1</literal>
-        client to backend node of ID 1.
+     Route 30% <acronym>SELECT</acronym> queries from <literal>myapp1</literal>
+     client to backend node of ID 1. The other 70% SELECT queries will be sent to other backend nodes.
         -->
-        全ての<literal>myapp1</literal>クライアントからの30%の<acronym>SELECT</acronym>クエリはIDが1のバックエンドノードに送る。
+        <literal>myapp1</literal>クライアントからの30%の<acronym>SELECT</acronym>クエリはIDが1のバックエンドノードに送る。
+     残りの70%のSELECTクエリは他のバックエンドノードに送る。
        </para>
        </listitem>
        <listitem>
@@ -1176,10 +1305,14 @@ app_name_redirect_preference_list = 'psql:primary,myapp1:1(0.3),myapp2:standby'
      <note>
       <para>
        <!--
-       <xref linkend="guc-app-name-redirect-preference-list"> takes precedence
-       over the <xref linkend="guc-database-redirect-preference-list">.
+       The priority of <xref linkend="guc-user-redirect-preference-list">,
+       <xref linkend="guc-database-redirect-preference-list"> and
+       <xref linkend="guc-app-name-redirect-preference-list"> are:
        -->
-       <xref linkend="guc-app-name-redirect-preference-list">は、<xref linkend="guc-database-redirect-preference-list">よりも優先されます。
+       <xref linkend="guc-user-redirect-preference-list">、<xref linkend="guc-database-redirect-preference-list">および<xref linkend="guc-app-name-redirect-preference-list">の優先順位は以下の通りです。
+       <programlisting>
+app_name_redirect_preference_list &gt; database_redirect_preference_list &gt; user_redirect_preference_list
+       </programlisting>
       </para>
       <para>
        <!--
@@ -1198,11 +1331,13 @@ app_name_redirect_preference_list = 'psql:primary,myapp1:1(0.3),myapp2:standby'
      <note>
       <para>
        <!--
-       In the settings of <xref linkend="guc-app-name-redirect-preference-list"> and
-       <xref linkend="guc-database-redirect-preference-list">, when multiple database
-       names and application names are matched, the first setting will be used.
+       In the settings of <xref linkend="guc-user-redirect-preference-list">,
+       <xref linkend="guc-database-redirect-preference-list"> and
+       <xref linkend="guc-app-name-redirect-preference-list">,
+       when multiple database names and application names are matched,
+       the first setting will be used.
        -->
-       <xref linkend="guc-app-name-redirect-preference-list">及び<xref linkend="guc-database-redirect-preference-list">の設定では、複数のデータベース名やアプリケーション名にマッチした場合、最初の設定が反映されます。
+       <xref linkend="guc-user-redirect-preference-list">、<xref linkend="guc-database-redirect-preference-list">および<xref linkend="guc-app-name-redirect-preference-list">の設定では、複数のユーザ名やデータベース名、アプリケーション名にマッチした場合、最初の設定が反映されます。
       </para>
       <para>
        <!--
index f987005d9470ef7e0d0116ce540eced570db926e..b14d4f97980ee4aa4555f461fef4bb6363171fe4 100644 (file)
@@ -726,6 +726,79 @@ primary_routing_query_pattern_list = 'SELECT \* FROM table_name1\;;SELECT col1,
     </listitem>
    </varlistentry>
 
+   <varlistentry id="guc-user-redirect-preference-list" xreflabel="user_redirect_preference_list">
+    <term><varname>user_redirect_preference_list</varname> (<type>string</type>)
+     <indexterm>
+      <primary><varname>user_redirect_preference_list</varname> configuration parameter</primary>
+     </indexterm>
+    </term>
+    <listitem>
+     <para>
+      Specifies the list of <replaceable>"user-name:node id(ratio)"</replaceable> pairs
+      to send <acronym>SELECT</acronym> queries to a particular backend
+      node for a particular user connection at a specified load balance ratio.
+      The load balance ratio specifies a value between 0 and 1. The default is 1.0.
+     </para>
+     <para>
+      For example, by specifying "user1:1(0.5)", <productname>Pgpool-II</productname>
+      will redirect 50% <acronym>SELECT</acronym> queries to the backend node of ID 1 for
+      the connection of user <literal>user1</literal>.
+     </para>
+     <para>
+      You can specify multiple <replaceable>"user-name:node id(ratio)"</replaceable> pairs
+      by separating them using comma (,).
+     </para>
+     <para>
+      Regular expressions are also accepted for user name.
+      You can use special keywords as <replaceable>node id</replaceable>.
+      If <emphasis>"primary"</emphasis> is specified, queries are sent to the primary node, and
+      if <emphasis>"standby"</emphasis> is specified, one of the standby nodes are selected randomly
+      based on load balance ratio.
+     </para>
+
+     <example id="example-user-redirect-list">
+      <title>Using user_redirect_preference_list</title>
+      <para>
+       If you want to configure the following <acronym>SELECT</acronym> query routing rules:
+      </para>
+
+      <itemizedlist>
+       <listitem>
+        <para>
+         Route all <acronym>SELECT</acronym> queries from the connections
+         using user <literal>postgres</literal> to the primary backend node.
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+         Route 30% <acronym>SELECT</acronym> queries from the connections
+         using user <literal>user0</literal> or <literal>user1</literal>
+         to backend node of ID 1.
+         The other 70% <acronym>SELECT</acronym> queries will be sent to other backend nodes.
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+         Route all <acronym>SELECT</acronym> queries from the connections
+         using user <literal>user2</literal> to standby backend nodes.
+        </para>
+       </listitem>
+
+      </itemizedlist>
+      <para>
+       then the <xref linkend="guc-user-redirect-preference-list"> will be configured as follows:
+       <programlisting>
+user_redirect_preference_list = 'postgres:primary,user[01]:1(0.3),user2:standby'
+       </programlisting>
+      </para>
+     </example>
+
+     <para>
+      This parameter can be changed by reloading the <productname>Pgpool-II</> configurations.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry id="guc-database-redirect-preference-list" xreflabel="database_redirect_preference_list">
     <term><varname>database_redirect_preference_list</varname> (<type>string</type>)
      <indexterm>
@@ -742,16 +815,18 @@ primary_routing_query_pattern_list = 'SELECT \* FROM table_name1\;;SELECT col1,
      <para>
       For example, by specifying "test:1(0.5)", <productname>Pgpool-II</productname>
       will redirect 50% <acronym>SELECT</acronym> queries to the backend node of ID 1 for
-      the connection to "test" database.
-      You can specify multiple <replaceable>"database name:node id"</replaceable> pair by separating them
-      using comma (,).
+      the connection to <literal>test</literal> database.
+     </para>
+     <para>
+      You can specify multiple <replaceable>"database-name:node id(ratio)"</replaceable> pairs
+      by separating them using comma (,).
      </para>
      <para>
       Regular expressions are also accepted for database name.
       You can use special keywords as <replaceable>node id</replaceable>.
       If <emphasis>"primary"</emphasis> is specified, queries are sent to the primary node, and
       if <emphasis>"standby"</emphasis> is specified, one of the standby nodes are selected randomly
-      based on weights (<xref linkend="guc-backend-weight">).
+      based on load balance ratio.
      </para>
 
      <example id="example-database-redirect-list">
@@ -762,31 +837,31 @@ primary_routing_query_pattern_list = 'SELECT \* FROM table_name1\;;SELECT col1,
 
       <itemizedlist>
        <listitem>
-       <para>
-        Route all <acronym>SELECT</acronym> queries on <literal>postgres</literal>
-        database to the primary backend node.
-       </para>
+        <para>
+         Route all <acronym>SELECT</acronym> queries on <literal>postgres</literal>
+         database to the primary backend node.
+        </para>
        </listitem>
        <listitem>
-       <para>
-        Route 30% <acronym>SELECT</acronym> queries on <literal>mydb0</literal> or on
-        <literal>mydb1</literal> databases to backend node of ID.
-        The other 70% <acronym>SELECT</acronym> queries will be sent to other backend nodes.
-       </para>
+        <para>
+         Route 30% <acronym>SELECT</acronym> queries on <literal>mydb0</literal> or on
+         <literal>mydb1</literal> databases to backend node of ID 1.
+         The other 70% <acronym>SELECT</acronym> queries will be sent to other backend nodes.
+        </para>
        </listitem>
        <listitem>
-       <para>
-        Route all <acronym>SELECT</acronym> queries on <literal>mydb2</literal>
-        database to standby backend nodes.
-       </para>
+        <para>
+         Route all <acronym>SELECT</acronym> queries on <literal>mydb2</literal>
+         database to standby backend nodes.
+        </para>
        </listitem>
 
       </itemizedlist>
       <para>
        then the <xref linkend="guc-database-redirect-preference-list"> will be configured as follows:
-       <programlisting>
+       <programlisting>
 database_redirect_preference_list = 'postgres:primary,mydb[01]:1(0.3),mydb2:standby'
-       </programlisting>
+       </programlisting>
       </para>
      </example>
 
@@ -808,6 +883,9 @@ database_redirect_preference_list = 'postgres:primary,mydb[01]:1(0.3),mydb2:stan
       Specifies the list of <replaceable>"application-name:node id(ratio)"</replaceable> pairs
       to send <acronym>SELECT</acronym> queries to a particular backend
       node for a particular client application connection at a specified load balance ratio.
+      The load balance ratio specifies a value between 0 and 1. The default is 1.0.
+      You can specify multiple <replaceable>"application-name:node id(ratio)"</replaceable> pairs
+      by separating them using comma (,).
      </para>
 
      <note>
@@ -833,12 +911,11 @@ database_redirect_preference_list = 'postgres:primary,mydb[01]:1(0.3),mydb2:stan
      </note>
 
      <para>
-      The notion of <xref linkend="guc-app-name-redirect-preference-list">
-       is same as the <xref linkend="guc-database-redirect-preference-list">
-       thus you can also use the regular expressions for application names.
-       Similarly special keyword <emphasis>"primary"</emphasis> indicates the primary node and
-       <emphasis>"standby"</emphasis> indicates one of standby nodes.
-       The load balance weight specifies a value between 0 and 1. The default is 1.0.
+      Regular expressions are also accepted for database name.
+      You can use special keywords as <replaceable>node id</replaceable>.
+      If <emphasis>"primary"</emphasis> is specified, queries are sent to the primary node, and
+      if <emphasis>"standby"</emphasis> is specified, one of the standby nodes are selected randomly
+      based on load balance ratio.
      </para>
 
      <example id="example-app-name-redirect-list">
@@ -849,37 +926,41 @@ database_redirect_preference_list = 'postgres:primary,mydb[01]:1(0.3),mydb2:stan
 
       <itemizedlist>
        <listitem>
-       <para>
-        Route all <acronym>SELECT</acronym> from <literal>psql</literal>
-        client to the primary backend node.
-       </para>
+        <para>
+         Route all <acronym>SELECT</acronym> from <literal>psql</literal>
+         client to the primary backend node.
+        </para>
        </listitem>
        <listitem>
-       <para>
-        Route 30% <acronym>SELECT</acronym> queries from <literal>myapp1</literal>
-        client to backend node of ID 1. The other 70% SELECT queries will be sent to other backend nodes.
-       </para>
+        <para>
+         Route 30% <acronym>SELECT</acronym> queries from <literal>myapp1</literal>
+         client to backend node of ID 1. The other 70% SELECT queries will be sent to other backend nodes.
+        </para>
        </listitem>
        <listitem>
-       <para>
-        Route all <acronym>SELECT</acronym> queries from <literal>myapp2</literal>
-        client to standby backend nodes.
-       </para>
+        <para>
+         Route all <acronym>SELECT</acronym> queries from <literal>myapp2</literal>
+         client to standby backend nodes.
+        </para>
        </listitem>
 
       </itemizedlist>
       <para>
        then the <xref linkend="guc-app-name-redirect-preference-list"> will be configured as follows:
-       <programlisting>
+       <programlisting>
 app_name_redirect_preference_list = 'psql:primary,myapp1:1(0.3),myapp2:standby'
-       </programlisting>
+       </programlisting>
       </para>
      </example>
 
      <note>
       <para>
-       <xref linkend="guc-app-name-redirect-preference-list"> takes precedence
-       over the <xref linkend="guc-database-redirect-preference-list">.
+       The priority of <xref linkend="guc-user-redirect-preference-list">,
+       <xref linkend="guc-database-redirect-preference-list"> and
+       <xref linkend="guc-app-name-redirect-preference-list"> are:
+       <programlisting>
+app_name_redirect_preference_list &gt; database_redirect_preference_list &gt; user_redirect_preference_list
+       </programlisting>
       </para>
       <para>
        For example, if you set
@@ -891,9 +972,11 @@ app_name_redirect_preference_list = 'psql:primary,myapp1:1(0.3),myapp2:standby'
 
      <note>
       <para>
-       By specifying of <xref linkend="guc-app-name-redirect-preference-list"> and
-       <xref linkend="guc-database-redirect-preference-list">, when multiple database
-        names and application names are matched, the first setting will be used.
+       By specifying of <xref linkend="guc-user-redirect-preference-list">,
+       <xref linkend="guc-database-redirect-preference-list"> and
+       <xref linkend="guc-app-name-redirect-preference-list">,
+       when multiple database names and application names are matched,
+       the first setting will be used.
       </para>
       <para>
        For example, if you set
@@ -910,7 +993,7 @@ app_name_redirect_preference_list = 'psql:primary,myapp1:1(0.3),myapp2:standby'
        driver option <literal>"ApplicationName"</literal> and
        <literal>"assumeMinServerVersion=9.0"</literal>.
        So if you want to use the <xref linkend="guc-app-name-redirect-preference-list">
-       feature through <acronym>JDBC</acronym>, Use PostgreSQL-9.4 or later version of the driver.
+       feature through <acronym>JDBC</acronym>, Use PostgreSQL-9.4 or later version of the driver.
       </para>
      </caution>
 
index 049cd73d5c3f5efe4c5206facaa0a9ec48e3611f..105d20840e9ccc89725fefb41952b4036a5c03e8 100644 (file)
@@ -96,6 +96,7 @@ static bool get_index_in_var_name(struct config_generic *record,
                                          const char *name, int *index, int elevel);
 
 
+static bool MakeUserRedirectListRegex(char *newval, int elevel);
 static bool MakeDBRedirectListRegex(char *newval, int elevel);
 static bool MakeAppRedirectListRegex(char *newval, int elevel);
 static bool MakeDMLAdaptiveObjectRelationList(char *newval, int elevel);
@@ -817,6 +818,19 @@ static struct config_bool ConfigureNamesBool[] =
 
 static struct config_string ConfigureNamesString[] =
 {
+       {
+               {"user_redirect_preference_list", CFGCXT_RELOAD, STREAMING_REPLICATION_CONFIG,
+                       "redirect by user name.",
+                       CONFIG_VAR_TYPE_STRING, false, 0
+               },
+               &g_pool_config.user_redirect_preference_list,   /* variable */
+               NULL,                                   /* boot value */
+               NULL,                                   /* assign_func */
+               NULL,                                   /* check_func */
+               MakeUserRedirectListRegex,      /* process func */
+               NULL                                    /* show hook */
+       },
+
        {
                {"database_redirect_preference_list", CFGCXT_RELOAD, STREAMING_REPLICATION_CONFIG,
                        "redirect by database name.",
@@ -5124,6 +5138,48 @@ MakeDBRedirectListRegex(char *newval, int elevel)
        return true;
 }
 
+static bool
+MakeUserRedirectListRegex(char *newval, int elevel)
+{
+       /* TODO Deal with the memory */
+       int                     i;
+       Left_right_tokens *lrtokens;
+
+       if (newval == NULL)
+       {
+               pool_config->redirect_usernames = NULL;
+               pool_config->user_redirect_tokens = NULL;
+               return true;
+       }
+
+       lrtokens = create_lrtoken_array();
+       extract_string_tokens2(newval, ",", ':', lrtokens);
+
+       pool_config->redirect_usernames = create_regex_array();
+       pool_config->user_redirect_tokens = lrtokens;
+
+       for (i = 0; i < lrtokens->pos; i++)
+       {
+               if (!check_redirect_node_spec(lrtokens->token[i].right_token))
+               {
+                       ereport(elevel,
+                                       (errmsg("invalid configuration for key \"user_redirect_preference_list\""),
+                                        errdetail("wrong redirect db node spec: \"%s\"", lrtokens->token[i].right_token)));
+                       return false;
+               }
+
+               if (*(lrtokens->token[i].left_token) == '\0' ||
+                       add_regex_array(pool_config->redirect_usernames, lrtokens->token[i].left_token))
+               {
+                       ereport(elevel,
+                                       (errmsg("invalid configuration for key \"user_redirect_preference_list\""),
+                                        errdetail("wrong redirect user name regular expression: \"%s\"", lrtokens->token[i].left_token)));
+                       return false;
+               }
+       }
+       return true;
+}
+
 /* Read the pgpool_node_id file */
 static bool
 SetPgpoolNodeId(int elevel)
index 07c6d767886a5e2f82737832f9c5cff89d911ea9..311b75faac12ac4f3b87eb142679e1a114fdf1df 100644 (file)
@@ -503,6 +503,17 @@ typedef struct
        int                     current_memqcache_table_pattern_size;   /* size of the regex
                                                                                                                 * pattern array */
 
+       /*
+        * user_redirect_preference_list =
+        * 'postgres:primary,user[0-4]:1,user[5-9]:2'
+        */
+       char       *user_redirect_preference_list;      /* raw string in
+                                                                                                        * pgpool.conf */
+       RegArray   *redirect_usernames; /* Precompiled regex patterns for db
+                                                                        * preference list */
+       Left_right_tokens *user_redirect_tokens;        /* db redirect for dbname and node
+                                                                                        * string */
+
        /*
         * database_redirect_preference_list =
         * 'postgres:primary,mydb[0-4]:1,mydb[5-9]:2'
index 2d786dbb143b4d1b8e2b932d95d9231d5bb811d9..a81dfd170088fb812d441cbc5ce99230f35e50a1 100644 (file)
@@ -309,7 +309,8 @@ select_load_balancing_node(void)
                                r;
        int                     i;
        int                     index_db = -1,
-                               index_app = -1;
+                               index_app = -1,
+                               index_user = -1;
        POOL_SESSION_CONTEXT *ses = pool_get_session_context(false);
        int                     tmp;
        int                     no_load_balance_node_id = -2;
@@ -329,6 +330,33 @@ select_load_balancing_node(void)
        r = (((double) random()) / RAND_MAX);
 #endif
 
+       /*
+        * Check user_redirect_preference_list
+        */
+       if (SL_MODE && pool_config->redirect_usernames)
+       {
+               char       *user = MAIN_CONNECTION(ses->backend)->sp->user;
+
+               /*
+                * Check to see if the user matches any of
+                * user_redirect_preference_list
+                */
+               index_user = regex_array_match(pool_config->redirect_usernames, user);
+               if (index_user >= 0)
+               {
+                       /* Matches */
+                       ereport(DEBUG1,
+                                       (errmsg("selecting load balance node user matched"),
+                                        errdetail("username: %s index is %d dbnode is %s weight is %f", user, index_user,
+                                                          pool_config->user_redirect_tokens->token[index_user].right_token,
+                                                          pool_config->user_redirect_tokens->token[index_user].weight_token)));
+
+                       tmp = choose_db_node_id(pool_config->user_redirect_tokens->token[index_user].right_token);
+                       if (tmp == -1 || (tmp >= 0 && VALID_BACKEND_RAW(tmp)))
+                               suggested_node_id = tmp;
+               }
+       }
+
        /*
         * Check database_redirect_preference_list
         */
@@ -343,6 +371,13 @@ select_load_balancing_node(void)
                index_db = regex_array_match(pool_config->redirect_dbnames, database);
                if (index_db >= 0)
                {
+                       /*
+                        * if the database name matches any of
+                        * database_redirect_preference_list,
+                        * user_redirect_preference_list will be ignored.
+                        */
+                       index_user = -1;
+
                        /* Matches */
                        ereport(DEBUG1,
                                        (errmsg("selecting load balance node db matched"),
@@ -382,6 +417,7 @@ select_load_balancing_node(void)
                                 * app_name_redirect_preference_list,
                                 * database_redirect_preference_list will be ignored.
                                 */
+                               index_user = -1;
                                index_db = -1;
 
                                /* Matches */
@@ -491,7 +527,8 @@ select_load_balancing_node(void)
                 * choose load balance node from other nodes.
                 */
                if ((index_db >= 0 && r <= pool_config->db_redirect_tokens->token[index_db].weight_token) ||
-                       (index_app >= 0 && r <= pool_config->app_name_redirect_tokens->token[index_app].weight_token))
+                       (index_app >= 0 && r <= pool_config->app_name_redirect_tokens->token[index_app].weight_token) ||
+                       (index_user >= 0 && r <= pool_config->user_redirect_tokens->token[index_user].weight_token))
                {
                        ereport(DEBUG1,
                                        (errmsg("selecting load balance node"),
@@ -507,7 +544,8 @@ select_load_balancing_node(void)
        {
                /* If the weight is less than random rate then send to primary. */
                if ((index_db >= 0 && r > pool_config->db_redirect_tokens->token[index_db].weight_token) ||
-                       (index_app >= 0 && r > pool_config->app_name_redirect_tokens->token[index_app].weight_token))
+                       (index_app >= 0 && r > pool_config->app_name_redirect_tokens->token[index_app].weight_token) ||
+                       (index_user >= 0 && r > pool_config->user_redirect_tokens->token[index_user].weight_token))
                {
                        ereport(DEBUG1,
                                        (errmsg("selecting load balance node"),
index f4397d2ffe1f918e2ee524dd96128aefec858589..7eb4d5a512d5fe187084bc237bf679249d8a7673 100644 (file)
@@ -437,6 +437,11 @@ backend_clustering_mode = 'streaming_replication'
                                    # Regexp are accepted
                                    # valid for streaming replicaton mode only.
 
+#user_redirect_preference_list = ''
+                                   # comma separated list of pairs of user name and node id.
+                                   # example: postgres:primary,user[0-4]:1,user[5-9]:2'
+                                   # valid for streaming replicaton mode only.
+
 #database_redirect_preference_list = ''
                                    # comma separated list of pairs of database and node id.
                                    # example: postgres:primary,mydb[0-4]:1,mydb[5-9]:2'
index 951c803774d5730048732d436a81f2d7abc06810..25d2a7eff04564e67b6e1b34a916cb711a238ecb 100644 (file)
@@ -1 +1 @@
-SELECT 'test9'
+SELECT 'test16'
index 9c28512cb0a39ee6a11345eaba8069ef48c4819b..d2b4704d262abc406f4a9968ef5957e80c7240a8 100644 (file)
@@ -1 +1 @@
-SELECT 'test11'
+SELECT 'test18'
index df1dae56e762c004b7eaee1d0ae7525ee46b0bfa..40e33394606f5ea467baaefa91cc1f0a46b6e175 100755 (executable)
@@ -1,12 +1,13 @@
 #!/usr/bin/env bash
 #-------------------------------------------------------------------
-# test script for database_redirect_preference_list and app_name_redirect_preference_list.
+# test script for user_redirect_preference_list, database_redirect_preference_list and app_name_redirect_preference_list.
 # requires pgbench.
 #
 source $TESTLIBS
 TESTDIR=testdir
 PSQL=$PGBIN/psql
 CREATEDB=$PGBIN/createdb
+CREATEUSER=$PGBIN/createuser
 PGBENCH=$PGBENCH_PATH
 
 function getnode()
@@ -25,11 +26,16 @@ echo "done."
 
 source ./bashrc.ports
 
-echo "database_redirect_preference_list = 'postgres:primary,test:1,mydb[5-9]:2,test2:standby,test3:primary(0.0),test4:standby(0.0),test5:primary(1.0)'" >> etc/pgpool.conf
-
 # disable delay_threshold so that replication delay does not affect the tests.
 echo "delay_threshold = 0" >> etc/pgpool.conf
 
+ok=yes
+#-------------------------------------------------------------------
+# Test user_redirect_preference_list
+#-------------------------------------------------------------------
+
+echo "user_redirect_preference_list = 'user1:primary,user2:1,user3:standby,user4:primary(1.0),user5:standby(0.0),user[6-9]:2'" >> etc/pgpool.conf
+
 ./startall
 
 export PGPORT=$PGPOOL_PORT
@@ -37,85 +43,160 @@ wait_for_pgpool_startup
 
 $PSQL -c "show pool_nodes" postgres
 
-$CREATEDB mydb6
-$CREATEDB test2
-$CREATEDB test3
-$CREATEDB test4
-$CREATEDB test5
+$CREATEUSER user1
+$CREATEUSER user2
+$CREATEUSER user3
+$CREATEUSER user4
+$CREATEUSER user5
+$CREATEUSER user6
 
 # check to see if all databases have been replicated
-
 for p in 3 4
 do
     # set standby port
     myport=`expr $PGPOOL_PORT + $p`
 
-    for r in 1 2 3 4 5
-    do
-       ok=true
-       for i in mydb6 test2 test3 test4 test5
+       for r in 1 2 3 4 5
        do
-           echo "try to connect to $i:$myport"
-           $PSQL -p $myport -c "select 1" $i
-           if [ $? != 0 ];then
-               ok=false
-               break
-           fi
+               is_replicated=true
+               for i in user1 user2 user3 user4 user5 user6
+               do
+                       echo "try to connect to PostgreSQL using user $i:$myport"
+                       $PSQL -p $myport -U $i -c "select 1" test
+                       if [ $? != 0 ];then
+                               is_replicated=false
+                               break
+                       fi
+               done
+               if [ $is_replicated = "false" ];then
+                       sleep 1
+               else
+                       break
+               fi
        done
-       if [ $ok = "false" ];then
-           sleep 1
-       else
-           break
-       fi
-    done
 done
 
-$PGBENCH -i postgres
+# Test1: should be redirect to primary (node 0)
+$PSQL -U user1 -c "SELECT 'test1'" test
+test `getnode "'test1'"` -eq 0 || ok=ng
+echo $ok
 
-ok=yes
+# Test2: should be redirect to node 1
+$PSQL -U user2 -c "SELECT 'test2'" test
+test `getnode "'test2'"` -eq 1 || ok=ng
+echo $ok
 
-# should be redirect to primary (node 0)
-$PSQL -c "SELECT 'test1'" postgres
+# Test3: should be redirect to either node 1 or 2 (standby)
+$PSQL -U user3 -c "SELECT 'test3'" test
+test `getnode "'test3'"` -eq 1 -o `getnode "test3"` -eq 2 || ok=ng
+echo $ok
 
-test `getnode "'test1'"` -eq 0 || ok=ng
+# Test4: should be redirect to primary (node 0)
+$PSQL -U user4 -c "SELECT 'test4'" test
+test `getnode "'test4'"` -eq 0 || ok=ng
 echo $ok
 
-# should be redirect to node 1
-$PSQL -c "SELECT 'test2'" test
+# Test5: should be redirect to primary (node 0)
+$PSQL -U user5 -c "SELECT 'test5'" test
+test `getnode "'test5'"` -eq 0 || ok=ng
+echo $ok
 
-test `getnode "'test2'"` -eq 1 || ok=ng
+# Test6: should be redirect to node 2
+$PSQL -U user6 -c "SELECT 'test6'" test
+test `getnode "'test6'"` -eq 2 || ok=ng
 echo $ok
 
-# should be redirect to node 2
-$PSQL -c "SELECT 'test3'" mydb6
+#-------------------------------------------------------------------
+# Test database_redirect_preference_list
+#-------------------------------------------------------------------
 
-test `getnode "'test3'"` -eq 2 || ok=ng
+echo "database_redirect_preference_list = 'postgres:primary,test:1,mydb[5-9]:2,test2:standby,test3:primary(0.0),test4:standby(0.0),test5:primary(1.0)'" >> etc/pgpool.conf
 
+./pgpool_reload
+sleep 10
+
+wait_for_pgpool_startup
+
+$CREATEDB mydb6
+$CREATEDB test2
+$CREATEDB test3
+$CREATEDB test4
+$CREATEDB test5
+
+# check to see if all databases have been replicated
+for p in 3 4
+do
+    # set standby port
+    myport=`expr $PGPOOL_PORT + $p`
+
+       for r in 1 2 3 4 5
+       do
+
+               is_replicated=true
+               for i in mydb6 test2 test3 test4 test5
+               do
+                       echo "try to connect to $i:$myport"
+                       $PSQL -p $myport -c "select 1" $i
+                       if [ $? != 0 ];then
+                               is_replicated=false
+                               break
+                       fi
+               done
+               if [ $is_replicated = "false" ];then
+                       sleep 1
+               else
+                       break
+               fi
+       done
+done
+
+# Test7: should be redirect to primary (node 0)
+$PSQL -c "SELECT 'test7'" postgres
+test `getnode "'test7'"` -eq 0 || ok=ng
 echo $ok
-# should be redirect to either node 1 or 2
-$PSQL -c "SELECT 'test4'" test2
 
-test `getnode "'test4'"` -eq 1 -o `getnode "test4"` -eq 2 || ok=ng
+# Test8: should be redirect to node 1
+$PSQL -c "SELECT 'test8'" test
+test `getnode "'test8'"` -eq 1 || ok=ng
 echo $ok
 
-# should be redirect to either node 1 or 2
-$PSQL -c "SELECT 'test5'" test3
+# Test9: should be redirect to node 2
+$PSQL -c "SELECT 'test9'" mydb6
+test `getnode "'test9'"` -eq 2 || ok=ng
+echo $ok
 
-test `getnode "'test5'"` -eq 1 -o `getnode "test5"` -eq 2 || ok=ng
+# Test10: should be redirect to either node 1 or 2
+$PSQL -c "SELECT 'test10'" test2
+test `getnode "'test10'"` -eq 1 -o `getnode "test10"` -eq 2 || ok=ng
 echo $ok
 
-# should be redirect to primary (node 0)
-$PSQL -c "SELECT 'test6'" test4
+# Test11: should be redirect to either node 1 or 2
+$PSQL -c "SELECT 'test11'" test3
+test `getnode "'test11'"` -eq 1 -o `getnode "test11"` -eq 2 || ok=ng
+echo $ok
 
-test `getnode "'test6'"` -eq 0 || ok=ng
+# Test12: should be redirect to primary (node 0)
+$PSQL -c "SELECT 'test12'" test4
+test `getnode "'test12'"` -eq 0 || ok=ng
 echo $ok
 
-# should be redirect to primary (node 0)
-$PSQL -c "SELECT 'test7'" test5
+# Test13: should be redirect to primary (node 0)
+$PSQL -c "SELECT 'test13'" test5
+test `getnode "'test13'"` -eq 0 || ok=ng
+echo $ok
 
-test `getnode "'test7'"` -eq 0 || ok=ng
+# Test14: For example:
+# if it matches both of user_redirect_preference_list and database_redirect_preference_list,
+# should be redirect to node 1 because database name is test
+# user_redirect_preference_list = 'user4:primary(1.0)'
+# database_redirect_preference_list = 'test:1'
+$PSQL -U user4 -c "SELECT 'test14'" test
+test `getnode "'test14'"` -eq 1 || ok=ng
 
-echo $ok
+#-------------------------------------------------------------------
+# Test app_name_redirect_preference_list
+#-------------------------------------------------------------------
+$PGBENCH -i postgres
 
 echo "app_name_redirect_preference_list = 'psql:primary,pgbench:standby'" >> etc/pgpool.conf
 
@@ -124,16 +205,14 @@ sleep 10
 
 wait_for_pgpool_startup
 
-# should be redirect to node 0 because application name is psql
-$PSQL -c "SELECT 'test8'" mydb6
-
-test `getnode "'test8'"` -eq 0 || ok=ng
-
+# Test15: should be redirect to node 0 because application name is psql
+$PSQL -c "SELECT 'test15'" mydb6
+test `getnode "'test15'"` -eq 0 || ok=ng
 echo $ok
-# should be redirect to either node 1 or 2
-$PGBENCH -t 1 -f ../select.pgbench postgres
 
-test `getnode "'test9'"` -eq 1 -o `getnode "test9"` -eq 2 || ok=ng
+# Test16: should be redirect to either node 1 or 2
+$PGBENCH -t 1 -f ../select.pgbench postgres
+test `getnode "'test16'"` -eq 1 -o `getnode "test16"` -eq 2 || ok=ng
 echo $ok
 
 
@@ -144,16 +223,14 @@ sleep 10
 
 wait_for_pgpool_startup
 
-# should be redirect to either node 1 or 2
-$PSQL -c "SELECT 'test10'" mydb6
-
-test `getnode "'test10'"` -eq 1 -o `getnode "test10"` -eq 2 || ok=ng
+# Test17: should be redirect to either node 1 or 2
+$PSQL -c "SELECT 'test17'" mydb6
+test `getnode "'test17'"` -eq 1 -o `getnode "test17"` -eq 2 || ok=ng
 echo $ok
 
-# should be redirect to either node 1 or 2
+# Test18: should be redirect to either node 1 or 2
 $PGBENCH -t 1 -f ../select1.pgbench postgres
-
-test `getnode "'test11'"` -eq 1 -o `getnode "test11"` -eq 2 || ok=ng
+test `getnode "'test18'"` -eq 1 -o `getnode "test18"` -eq 2 || ok=ng
 echo $ok
 
 ./shutdownall
index bd9323fe355d76cf578abfcb6c36cceb3038bb4d..5b22ab20a1cbe3496432ab7b056d2dd20db21d00 100644 (file)
@@ -663,6 +663,11 @@ get_config(int *nrows)
        StrNCpy(status[i].desc, "follow primary command", POOLCONFIG_MAXDESCLEN);
        i++;
 
+       StrNCpy(status[i].name, "user_redirect_preference_list", POOLCONFIG_MAXNAMELEN);
+       snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->user_redirect_preference_list);
+       StrNCpy(status[i].desc, "redirect by user name", POOLCONFIG_MAXDESCLEN);
+       i++;
+
        StrNCpy(status[i].name, "database_redirect_preference_list", POOLCONFIG_MAXNAMELEN);
        snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->database_redirect_preference_list);
        StrNCpy(status[i].desc, "redirect by database name", POOLCONFIG_MAXDESCLEN);