Fully implement "disable_load_balance_on_write".
authorTatsuo Ishii <ishii@postgresql.org>
Mon, 23 Apr 2018 04:12:47 +0000 (13:12 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Mon, 23 Apr 2018 04:12:47 +0000 (13:12 +0900)
This feature allows to specify the behavior when a write query issued.
Except Japanese documents, all done.

22 files changed:
doc/src/sgml/loadbalance.sgml
src/context/pool_query_context.c
src/context/pool_session_context.c
src/protocol/pool_proto_modules.c
src/test/extended-query-test/expected/disable-load-balance-always.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance-default-simple.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance-default.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance-off.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance-simple.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-always.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-default-simple.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-default.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-off.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-simple.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-always.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-default-simple.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-default.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-off.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-simple.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance.data [new file with mode: 0644]

index 5f43922863a785bac515c5dff42df1522a0b2b67..18db5af81b40c533841ea0c4d373d9aeb4ebf202 100644 (file)
@@ -8,13 +8,12 @@
     works with Master Slave mode (<xref linkend="runtime-config-master-slave-mode">)
     and Replication mode (<xref linkend="runtime-config-replication-mode">). When enabled
     <productname>Pgpool-II</productname> sends the writing queries to the
-    <acronym>primay node</acronym> in Master Slave mode, all of the backend nodes
-    in Replication mode, and other queries get load balanced among all backend nodes.
-    To which node
-    the load balancing mechanism sends read queries is decided at the
-    session start time and will not be changed until the session
-    ends. The only exception is by writing special SQL comments. See
-    below for more details.
+    <acronym>primay node</acronym> in Master Slave mode, all of the
+    backend nodes in Replication mode, and other queries get load
+    balanced among all backend nodes.  To which node the load
+    balancing mechanism sends read queries is decided at the session
+    start time and will not be changed until the session ends. However
+    there are some exceptions.  See below for more details.
   </para>
   <note>
     <para>
 
  </sect2>
 
+ <sect2 id="runtime-config-writing-queries-may-affect-load-balancing">
+
+   <title>Writing queries may affect Load Balancing</title>
+   <para>
+     In general, read queries are load balanced if certain conditions
+     are met. However, writing queries may affect the load
+     balancing. Here "writing queries" mean all the queries except
+     below:
+   </para>
+
+   <para>
+   <itemizedlist>
+     <listitem>
+       <para>
+        SELECT/WITH without FOR UPDATE/SHARE
+       </para>
+     </listitem>
+
+     <listitem>
+       <para>
+        COPY TO STODUT
+       </para>
+     </listitem>
+
+     <listitem>
+       <para>
+        EXPLAIN
+       </para>
+     </listitem>        
+
+     <listitem>
+       <para>
+        EXPLAIN ANALYZE and the query is SELECT not including writing functions
+       </para>
+     </listitem>        
+
+     <listitem>
+       <para>
+        SHOW
+       </para>
+     </listitem>        
+
+   </itemizedlist>
+   </para>
+
+   <para>
+     If writing queires appear, succeeding read queries may not be
+     load balanced. i.e. sent to primary node (in streaming
+     replication mode) or master node (in other mode) depending on the
+     setting of <xref linkend="guc-disable-load-balance-on-write">.
+   </para>
+ </sect2>
+
  <sect2 id="runtime-config-load-balancing-in-streaming-raplication">
 
    <title>Load Balancing in Streaming Replication</title>
              SELECT not listed above
              </para>
            </listitem>
+
            <listitem>
              <para>
-             COPY TO
+             COPY TO STDOUT
              </para>
            </listitem>
+
+          <listitem>
+            <para>
+              EXPLAIN
+            </para>
+          </listitem>   
+
+          <listitem>
+            <para>
+              EXPLAIN ANALYZE and the query is SELECT not including writing functions
+            </para>
+          </listitem>   
+
+          <listitem>
+            <para>
+              SHOW
+            </para>
+          </listitem>   
+
          </itemizedlist>
         </para>
       </listitem>
@@ -705,6 +777,69 @@ app_name_redirect_preference_list = 'psql:primary,myapp1:1,myapp2:standby'
       </listitem>
     </varlistentry>
 
+   <varlistentry id="guc-disable-load-balance-on-write" xreflabel="disable_load_balance_on_write">
+      <term><varname>disable_load_balance_on_write</varname> (<type>string</type>)
+        <indexterm>
+          <primary><varname>disable_load_balance_on_write</varname> configuration parameter</primary>
+        </indexterm>
+      </term>
+      <listitem>
+        <para>
+         Specify load balance behavior after write queries appear.
+         This parameter is especially useful in streaming replication
+         mode. When write queries are sent to primary server, the
+         changes are applied to standby servers but there's a time
+         lag. So if a client read the same row right after the write
+         query, the client may not see the latest value of the
+         row. If that's the problem, clients should always read data
+         from the primary server. However this effectively disables
+         load balancing, which leads to lesser performance. This
+         parameter allows a fine tuning for the trade off between
+         not-clustering-aware applications compatibility and
+         performance.
+       </para>
+       <para>
+         If this parameter is set to <varname>off</varname>, read
+         queries are load balanced even if write queries appear. This
+         gives the best load balance performance but clients may see
+         older data. This is useful for an environment where
+         PostgreSQL parameter synchronous_commit = 'remote_apply', or
+         in the native replication mode, since there's no replication
+         delay in such environments.
+       </para>
+       <para>
+         If this parameter is set to <varname>transaction</varname>
+         and write queries appear in an explicit transaction,
+         subsequent read queries are not load balanced until the
+         transaction ends.  Please note that read queries not in an
+         explicit transaction are not affected by the parameter. This
+         setting gives the best balance in most cases and you should
+         start from this. This is the default and same behavior in
+         <productname>Pgpool-II 3.7</productname> or before.
+       </para>
+       <para>
+         If this parameter is set
+         to <varname>trans_transaction</varname> and write queries
+         appear in an explicit transaction, subsequent read queries
+         are not load balanced in the transaction and subsequent
+         explicit transaction until the session ends. So this
+         parameter is safer for older applications but give lesser
+         performance than <varname>transaction</varname>. Please note
+         that read queries not in an explicit transaction are not
+         affected by the parameter.
+       </para>
+
+       <para>
+         If this parameter is set to <varname>always</varname> and
+         write queries appear, subsequent read queries are not load
+         balanced until the session ends regardless they are in
+         explicit transactions or not. This gives the highest
+         compatibility with not-clustering-aware applications and the
+         lowest performance.
+       </para>
+      </listitem>
+    </varlistentry>
+
   </variablelist>
  </sect2>
 </sect1>
index d31966463d49bbeb6de668b2d04a921f06a53bd5..260f0ab72352f66ac57006a9947d61876ab34f69 100644 (file)
@@ -462,6 +462,11 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no
                {
                        pool_setall_node_to_be_sent(query_context);
                }
+               else if (pool_is_writing_transaction() &&
+                                pool_config->disable_load_balance_on_write == DLBOW_ALWAYS)
+               {
+                       pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
+               }
 
                /*
                 * Ok, we might be able to load balance the SELECT query.
index 5d4e2cbe15bd7170e825a329ef93bba7f45c2c80..f24a57311dff2b53a190ced7c6265dffca18fbe6 100644 (file)
@@ -1,12 +1,10 @@
 /* -*-pgsql-c-*- */
 /*
- *
- * $Header$
  *
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2017     PgPool Global Development Group
+ * Copyright (c) 2003-2018     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -607,10 +605,16 @@ void pool_set_sent_message_state(POOL_SENT_MESSAGE *message)
  */
 void pool_unset_writing_transaction(void)
 {
-       ereport(DEBUG1,
-                       (errmsg("session context: clearing writing transaction. DONE")));
-
-       pool_get_session_context(false)->writing_transaction = false;
+       /*
+        * If disable_transaction_on_write is 'always', then never turn off
+        * writing transaction flag.
+        */
+       if (pool_config->disable_load_balance_on_write != DLBOW_ALWAYS)
+       {
+               pool_get_session_context(false)->writing_transaction = false;
+               ereport(DEBUG1,
+                               (errmsg("session context: clearing writing transaction. DONE")));
+       }
 }
 
 /*
@@ -618,9 +622,16 @@ void pool_unset_writing_transaction(void)
  */
 void pool_set_writing_transaction(void)
 {
-       ereport(DEBUG1,
+       /*
+        * If disable_transaction_on_write is 'off', then never turn on writing
+        * transaction flag.
+        */
+       if (pool_config->disable_load_balance_on_write != DLBOW_OFF)
+       {
+               pool_get_session_context(false)->writing_transaction = true;
+               ereport(DEBUG1,
                        (errmsg("session context: setting writing transaction. DONE")));
-       pool_get_session_context(false)->writing_transaction = true;
+       }
 }
 
 /*
index 6d1203930693a44a4e83c96b8443ac3986a9836e..9447243f3955ab5f9b35c3d249daf269fd91c626 100644 (file)
@@ -918,7 +918,8 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
                         * explicit transaction, remember that we had a write
                         * query in this transaction.
                         */
-                       if (TSTATE(backend, MASTER_SLAVE ? PRIMARY_NODE_ID : REAL_MASTER_NODE_ID) == 'T')
+                       if (TSTATE(backend, MASTER_SLAVE ? PRIMARY_NODE_ID : REAL_MASTER_NODE_ID) == 'T' ||
+                               pool_config->disable_load_balance_on_write == DLBOW_ALWAYS)
                        {
                                pool_set_writing_transaction();
                        }
@@ -3732,11 +3733,12 @@ void pool_at_command_success(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *ba
        else if (!is_select_query(node, query))
        {
                /*
-                * If the query was not READ SELECT, and we are in an
-                * explicit transaction, remember that we had a write
-                * query in this transaction.
+                * If the query was not READ SELECT, and we are in an explicit
+                * transaction or disable_load_balance_on_write is 'ALWAYS', remember
+                * that we had a write query in this transaction.
                 */
-               if (TSTATE(backend, MASTER_SLAVE ? PRIMARY_NODE_ID : REAL_MASTER_NODE_ID) == 'T')
+               if (TSTATE(backend, MASTER_SLAVE ? PRIMARY_NODE_ID : REAL_MASTER_NODE_ID) == 'T' ||
+                       pool_config->disable_load_balance_on_write == DLBOW_ALWAYS)
                {
                        /* However, if the query is "SET TRANSACTION READ ONLY" or its variant,
                         * don't set it.
diff --git a/src/test/extended-query-test/expected/disable-load-balance-always.data b/src/test/extended-query-test/expected/disable-load-balance-always.data
new file mode 100644 (file)
index 0000000..e62a059
--- /dev/null
@@ -0,0 +1,117 @@
+FE=> Query(query="DROP TABLE IF EXISTS pgproto_test1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M table "pgproto_test1" does not exist, skipping F tablecmds.c L 914 R DropErrorMsgNonExistent )
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Query(query="CREATE TABLE pgproto_test1(i INT)")
+<= BE CommandComplete(CREATE TABLE)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="BEGIN")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="S1", query="SELECT 1")
+FE=> Parse(stmt="", query="INSERT INTO pgproto_test1 VALUES(1)")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Bind(stmt="S1", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="SELECT 2")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="COMMIT")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(BEGIN)
+<= BE ParseComplete
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(INSERT 0 1)
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="SELECT 3")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="BEGIN")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Bind(stmt="S1", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="SELECT 4")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="COMMIT")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Close(stmt="S1")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(BEGIN)
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(COMMIT)
+<= BE CloseComplete
+<= BE ReadyForQuery(I)
+FE=> Query(query="BEGIN")
+<= BE CommandComplete(BEGIN)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 1")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="INSERT INTO pgproto_test1 VALUES(1)")
+<= BE CommandComplete(INSERT 0 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 2")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="COMMIT")
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Query(query="SELECT 3")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(I)
+FE=> Query(query="BEGIN")
+<= BE CommandComplete(BEGIN)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 4")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="COMMIT")
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Query(query="DROP TABLE pgproto_test1")
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance-default-simple.data b/src/test/extended-query-test/expected/disable-load-balance-default-simple.data
new file mode 100644 (file)
index 0000000..2e3af4b
--- /dev/null
@@ -0,0 +1,46 @@
+FE=> Query(query="DROP TABLE IF EXISTS pgproto_test1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M table "pgproto_test1" does not exist, skipping F tablecmds.c L 914 R DropErrorMsgNonExistent )
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Query(query="CREATE TABLE pgproto_test1(i INT)")
+<= BE CommandComplete(CREATE TABLE)
+<= BE ReadyForQuery(I)
+FE=> Query(query="BEGIN")
+<= BE CommandComplete(BEGIN)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 1")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="INSERT INTO pgproto_test1 VALUES(1)")
+<= BE CommandComplete(INSERT 0 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 2")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="COMMIT")
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Query(query="SELECT 3")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(I)
+FE=> Query(query="BEGIN")
+<= BE CommandComplete(BEGIN)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 4")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="COMMIT")
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Query(query="DROP TABLE pgproto_test1")
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance-default.data b/src/test/extended-query-test/expected/disable-load-balance-default.data
new file mode 100644 (file)
index 0000000..7d8a15d
--- /dev/null
@@ -0,0 +1,82 @@
+FE=> Query(query="DROP TABLE IF EXISTS pgproto_test1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M table "pgproto_test1" does not exist, skipping F tablecmds.c L 914 R DropErrorMsgNonExistent )
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Query(query="CREATE TABLE pgproto_test1(i INT)")
+<= BE CommandComplete(CREATE TABLE)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="BEGIN")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="S1", query="SELECT 1")
+FE=> Parse(stmt="", query="INSERT INTO pgproto_test1 VALUES(1)")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Bind(stmt="S1", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="SELECT 2")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="COMMIT")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(BEGIN)
+<= BE ParseComplete
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(INSERT 0 1)
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="SELECT 3")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="BEGIN")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Bind(stmt="S1", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="SELECT 4")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="COMMIT")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Close(stmt="S1")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(BEGIN)
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(COMMIT)
+<= BE CloseComplete
+<= BE ReadyForQuery(I)
+FE=> Query(query="DROP TABLE pgproto_test1")
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance-off.data b/src/test/extended-query-test/expected/disable-load-balance-off.data
new file mode 100644 (file)
index 0000000..e62a059
--- /dev/null
@@ -0,0 +1,117 @@
+FE=> Query(query="DROP TABLE IF EXISTS pgproto_test1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M table "pgproto_test1" does not exist, skipping F tablecmds.c L 914 R DropErrorMsgNonExistent )
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Query(query="CREATE TABLE pgproto_test1(i INT)")
+<= BE CommandComplete(CREATE TABLE)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="BEGIN")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="S1", query="SELECT 1")
+FE=> Parse(stmt="", query="INSERT INTO pgproto_test1 VALUES(1)")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Bind(stmt="S1", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="SELECT 2")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="COMMIT")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(BEGIN)
+<= BE ParseComplete
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(INSERT 0 1)
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="SELECT 3")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="BEGIN")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Bind(stmt="S1", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="SELECT 4")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="COMMIT")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Close(stmt="S1")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(BEGIN)
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(COMMIT)
+<= BE CloseComplete
+<= BE ReadyForQuery(I)
+FE=> Query(query="BEGIN")
+<= BE CommandComplete(BEGIN)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 1")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="INSERT INTO pgproto_test1 VALUES(1)")
+<= BE CommandComplete(INSERT 0 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 2")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="COMMIT")
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Query(query="SELECT 3")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(I)
+FE=> Query(query="BEGIN")
+<= BE CommandComplete(BEGIN)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 4")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="COMMIT")
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Query(query="DROP TABLE pgproto_test1")
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance-simple.data b/src/test/extended-query-test/expected/disable-load-balance-simple.data
new file mode 100644 (file)
index 0000000..2e3af4b
--- /dev/null
@@ -0,0 +1,46 @@
+FE=> Query(query="DROP TABLE IF EXISTS pgproto_test1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M table "pgproto_test1" does not exist, skipping F tablecmds.c L 914 R DropErrorMsgNonExistent )
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Query(query="CREATE TABLE pgproto_test1(i INT)")
+<= BE CommandComplete(CREATE TABLE)
+<= BE ReadyForQuery(I)
+FE=> Query(query="BEGIN")
+<= BE CommandComplete(BEGIN)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 1")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="INSERT INTO pgproto_test1 VALUES(1)")
+<= BE CommandComplete(INSERT 0 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 2")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="COMMIT")
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Query(query="SELECT 3")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(I)
+FE=> Query(query="BEGIN")
+<= BE CommandComplete(BEGIN)
+<= BE ReadyForQuery(T)
+FE=> Query(query="SELECT 4")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(T)
+FE=> Query(query="COMMIT")
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Query(query="DROP TABLE pgproto_test1")
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance.data b/src/test/extended-query-test/expected/disable-load-balance.data
new file mode 100644 (file)
index 0000000..7d8a15d
--- /dev/null
@@ -0,0 +1,82 @@
+FE=> Query(query="DROP TABLE IF EXISTS pgproto_test1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M table "pgproto_test1" does not exist, skipping F tablecmds.c L 914 R DropErrorMsgNonExistent )
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Query(query="CREATE TABLE pgproto_test1(i INT)")
+<= BE CommandComplete(CREATE TABLE)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="BEGIN")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="S1", query="SELECT 1")
+FE=> Parse(stmt="", query="INSERT INTO pgproto_test1 VALUES(1)")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Bind(stmt="S1", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="SELECT 2")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="COMMIT")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(BEGIN)
+<= BE ParseComplete
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(INSERT 0 1)
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(COMMIT)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="SELECT 3")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ReadyForQuery(I)
+FE=> Parse(stmt="", query="BEGIN")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Bind(stmt="S1", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="SELECT 4")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Parse(stmt="", query="COMMIT")
+FE=> Bind(stmt="", portal="")
+FE=> Execute(portal="")
+FE=> Close(stmt="S1")
+FE=> Sync
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(BEGIN)
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE DataRow
+<= BE CommandComplete(SELECT 1)
+<= BE ParseComplete
+<= BE BindComplete
+<= BE CommandComplete(COMMIT)
+<= BE CloseComplete
+<= BE ReadyForQuery(I)
+FE=> Query(query="DROP TABLE pgproto_test1")
+<= BE CommandComplete(DROP TABLE)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/extra_scripts/disable-load-balance-always.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-always.data
new file mode 100644 (file)
index 0000000..c9eeb61
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# expected results: Parse: 1 Parse: 0 Execute: 0 Parse: 0 Execute: 0
+# Parse: 0 Execute: 0 Parse: 0 Execute: 0 Parse: 0 Execute: 0
+# SELECT: 0 SELECT: 0 SELECT: 0 SELECT: 0
+set 1 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+grep "SELECT" $PGPOOLLOG |awk '{print $9}' | while read node
+do
+    if [ $1 -ne $node ]
+    then
+       echo "expected: $1 result: $node"
+       exit 99
+    fi
+    shift
+done
+
+if [ $? = 99 ]
+then
+   exit 1
+fi
+
+exit 0
+   
diff --git a/src/test/extended-query-test/extra_scripts/disable-load-balance-default-simple.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-default-simple.data
new file mode 100644 (file)
index 0000000..5e91dc0
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# expected results: SELECT: 1 SELECT: 0 SELECT: 1 SELECT: 1
+set 1 0 1 1
+
+grep "SELECT" $PGPOOLLOG |awk '{print $9}' | while read node
+do
+    if [ $1 -ne $node ]
+    then
+       echo "expected: $1 result: $node"
+       exit 99
+    fi
+    shift
+done
+
+if [ $? = 99 ]
+then
+   exit 1
+fi
+
+exit 0
+   
diff --git a/src/test/extended-query-test/extra_scripts/disable-load-balance-default.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-default.data
new file mode 100644 (file)
index 0000000..b02acb5
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+# expected results: Parse: 1 Parse: 0 Execute: 0 Parse: 0 Execute: 0
+# Parse: 1 Execute: 1 Parse: 1 Execute: 1 Parse: 1 Execute: 1
+set 1 0 0 0 0 1 1 1 1 1
+
+grep "SELECT" $PGPOOLLOG |awk '{print $9}' | while read node
+do
+    if [ $1 -ne $node ]
+    then
+       echo "expected: $1 result: $node"
+       exit 99
+    fi
+    shift
+done
+
+if [ $? = 99 ]
+then
+   exit 1
+fi
+
+exit 0
+   
diff --git a/src/test/extended-query-test/extra_scripts/disable-load-balance-off.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-off.data
new file mode 100644 (file)
index 0000000..d0de7be
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# expected results: Parse: 1 Parse: 1 Execute: 1 Parse: 1 Execute: 1
+# Parse: 1 Execute: 1 Parse: 1 Execute: 1 Parse: 1 Execute: 1
+# SELECT: 1 SELECT: 1 SELECT: 1 SELECT: 1
+set 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+
+grep "SELECT" $PGPOOLLOG |awk '{print $9}' | while read node
+do
+    if [ $1 -ne $node ]
+    then
+       echo "expected: $1 result: $node"
+       exit 99
+    fi
+    shift
+done
+
+if [ $? = 99 ]
+then
+   exit 1
+fi
+
+exit 0
+   
diff --git a/src/test/extended-query-test/extra_scripts/disable-load-balance-simple.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-simple.data
new file mode 100644 (file)
index 0000000..cd351d2
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# expected results: SELECT: 1 SELECT: 0 SELECT: 1 SELECT: 0
+set 1 0 1 0
+
+grep "SELECT" $PGPOOLLOG |awk '{print $9}' | while read node
+do
+    if [ $1 -ne $node ]
+    then
+       echo "expected: $1 result: $node"
+       exit 99
+    fi
+    shift
+done
+
+if [ $? = 99 ]
+then
+   exit 1
+fi
+
+exit 0
+   
diff --git a/src/test/extended-query-test/extra_scripts/disable-load-balance.data b/src/test/extended-query-test/extra_scripts/disable-load-balance.data
new file mode 100644 (file)
index 0000000..c74fe44
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+# expected results: Parse: 1 Parse: 0 Execute: 0 Parse: 0 Execute: 0
+# Parse: 1 Execute: 1 Parse: 0 Execute: 0 Parse: 0 Execute: 0
+set 1 0 0 0 0 1 1 0 0 0 0
+
+grep "SELECT" $PGPOOLLOG |awk '{print $9}' | while read node
+do
+    if [ $1 -ne $node ]
+    then
+       echo "expected: $1 result: $node"
+       exit 99
+    fi
+    shift
+done
+
+if [ $? = 99 ]
+then
+   exit 1
+fi
+
+exit 0
+   
diff --git a/src/test/extended-query-test/tests/disable-load-balance-always.data b/src/test/extended-query-test/tests/disable-load-balance-always.data
new file mode 100644 (file)
index 0000000..1e0f9f7
--- /dev/null
@@ -0,0 +1,119 @@
+# Test for disable_load_balance_on_write feature (always).
+#
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+# Disable load balance in current transaction only.
+# (default behavior)
+
+# Create test table
+'Q'    "DROP TABLE IF EXISTS pgproto_test1"
+'Y'
+'Q'    "CREATE TABLE pgproto_test1(i INT)"
+'Y'
+
+# Start a transaction
+'P'    ""      "BEGIN" 0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Parse SELECT. This should be sent to node 1.
+'P'    "S1"    "SELECT 1"      0
+
+# Issue INSERT
+'P'    ""      "INSERT INTO pgproto_test1 VALUES(1)"   0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Bind/Execute SELECT. This should be sent to primary node.
+'B'    ""      "S1"    0       0       0
+'E'    ""      0
+
+# Issue another SELECT. This should be sent to primary node.
+'P'    ""      "SELECT 2"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue COMMIT
+'P'    ""      "COMMIT"        0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'S'
+'Y'
+
+# Issue another SELECT. This should be sent to primay node.
+'P'    ""      "SELECT 3"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'S'
+'Y'
+
+# Start a transaction
+'P'    ""      "BEGIN" 0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Bind/Execute SELECT. This should be sent to primary node because
+# disable_load_balance_on_write = 'always.
+'B'    ""      "S1"    0       0       0
+'E'    ""      0
+
+# Issue another SELECT. This should be sent to primary node.
+'P'    ""      "SELECT 4"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue COMMIT
+'P'    ""      "COMMIT"        0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'C'    'S'     "S1"
+'S'
+'Y'
+
+# Test for disable_load_balance_on_write = always feature
+# using simple queries.
+
+# Start a transaction
+'Q'    "BEGIN"
+'Y'
+
+# Issue Parse SELECT. This should be sent to node 0.
+'Q'    "SELECT 1"
+'Y'
+
+# Issue INSERT
+'Q'    "INSERT INTO pgproto_test1 VALUES(1)"
+'Y'
+
+# Issue another SELECT. This should be sent to primary node.
+'Q'    "SELECT 2"
+'Y'
+
+# Issue COMMIT
+'Q'    "COMMIT"
+'Y'
+
+# Issue another SELECT. This should be sent to primary node.
+'Q'    "SELECT 3"
+'Y'
+
+# Start a transaction
+'Q'    "BEGIN"
+'Y'
+
+# Issue another SELECT. This should be sent to primary node.
+'Q'    "SELECT 4"
+'Y'
+
+# Issue COMMIT
+'Q'    "COMMIT"
+'Y'
+
+# DROP test table
+'Q'    "DROP TABLE pgproto_test1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance-default-simple.data b/src/test/extended-query-test/tests/disable-load-balance-default-simple.data
new file mode 100644 (file)
index 0000000..3b0f676
--- /dev/null
@@ -0,0 +1,57 @@
+# Test for disable_load_balance_on_write feature
+# using simple queries.
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+# Disable load balance in current transaction only.
+# (default behavior)
+
+# Create test table
+'Q'    "DROP TABLE IF EXISTS pgproto_test1"
+'Y'
+'Q'    "CREATE TABLE pgproto_test1(i INT)"
+'Y'
+
+# Start a transaction
+'Q'    "BEGIN"
+'Y'
+
+# Issue Parse SELECT. This should be sent to node 1.
+'Q'    "SELECT 1"
+'Y'
+
+# Issue INSERT
+'Q'    "INSERT INTO pgproto_test1 VALUES(1)"
+'Y'
+
+# Issue another SELECT. This should be sent to primary node.
+'Q'    "SELECT 2"
+'Y'
+
+# Issue COMMIT
+'Q'    "COMMIT"
+'Y'
+
+# Issue another SELECT. This should be sent to node 1 because outside a transaction.
+'Q'    "SELECT 3"
+'Y'
+
+# Start a transaction
+'Q'    "BEGIN"
+'Y'
+
+# Issue another SELECT. This should be sent to primary node.
+'Q'    "SELECT 4"
+'Y'
+
+# Issue COMMIT
+'Q'    "COMMIT"
+'Y'
+
+# DROP test table
+'Q'    "DROP TABLE pgproto_test1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance-default.data b/src/test/extended-query-test/tests/disable-load-balance-default.data
new file mode 100644 (file)
index 0000000..74344f9
--- /dev/null
@@ -0,0 +1,80 @@
+# Test for disable_load_balance_on_write feature.
+#
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+# Disable load balance in current transaction only.
+# (default behavior)
+
+# Create test table
+'Q'    "DROP TABLE IF EXISTS pgproto_test1"
+'Y'
+'Q'    "CREATE TABLE pgproto_test1(i INT)"
+'Y'
+
+# Start a transaction
+'P'    ""      "BEGIN" 0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Parse SELECT. This should be sent to node 1.
+'P'    "S1"    "SELECT 1"      0
+
+# Issue INSERT
+'P'    ""      "INSERT INTO pgproto_test1 VALUES(1)"   0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Bind/Execute SELECT. This should be sent to primary node.
+'B'    ""      "S1"    0       0       0
+'E'    ""      0
+
+# Issue another SELECT. This should be sent to primary node.
+'P'    ""      "SELECT 2"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue COMMIT
+'P'    ""      "COMMIT"        0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'S'
+'Y'
+
+# Issue another SELECT. This should be sent to node 1 because outside a transaction.
+'P'    ""      "SELECT 3"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'S'
+'Y'
+
+# Start a transaction
+'P'    ""      "BEGIN" 0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Bind/Execute SELECT. This should be sent to node 1 because
+# disable_load_balance_on_write = 'transaction'.
+'B'    ""      "S1"    0       0       0
+'E'    ""      0
+
+# Issue another SELECT. This should be sent to node 1.
+'P'    ""      "SELECT 4"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue COMMIT
+'P'    ""      "COMMIT"        0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'C'    'S'     "S1"
+'S'
+'Y'
+
+# DROP test table
+'Q'    "DROP TABLE pgproto_test1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance-off.data b/src/test/extended-query-test/tests/disable-load-balance-off.data
new file mode 100644 (file)
index 0000000..fab4d6a
--- /dev/null
@@ -0,0 +1,119 @@
+# Test for disable_load_balance_on_write feature (off).
+#
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+# Disable load balance in current transaction only.
+# (default behavior)
+
+# Create test table
+'Q'    "DROP TABLE IF EXISTS pgproto_test1"
+'Y'
+'Q'    "CREATE TABLE pgproto_test1(i INT)"
+'Y'
+
+# Start a transaction
+'P'    ""      "BEGIN" 0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Parse SELECT. This should be sent to node 1.
+'P'    "S1"    "SELECT 1"      0
+
+# Issue INSERT
+'P'    ""      "INSERT INTO pgproto_test1 VALUES(1)"   0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Bind/Execute SELECT. This should be sent to standby node.
+'B'    ""      "S1"    0       0       0
+'E'    ""      0
+
+# Issue another SELECT. This should be sent to standby node.
+'P'    ""      "SELECT 2"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue COMMIT
+'P'    ""      "COMMIT"        0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'S'
+'Y'
+
+# Issue another SELECT. This should be sent to standby node.
+'P'    ""      "SELECT 3"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'S'
+'Y'
+
+# Start a transaction
+'P'    ""      "BEGIN" 0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Bind/Execute SELECT. This should be sent to standby node because
+# disable_load_balance_on_write = 'off'.
+'B'    ""      "S1"    0       0       0
+'E'    ""      0
+
+# Issue another SELECT. This should be sent to standby node.
+'P'    ""      "SELECT 4"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue COMMIT
+'P'    ""      "COMMIT"        0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'C'    'S'     "S1"
+'S'
+'Y'
+
+# Test for disable_load_balance_on_write = off feature
+# using simple queries.
+
+# Start a transaction
+'Q'    "BEGIN"
+'Y'
+
+# Issue Parse SELECT. This should be sent to node 1.
+'Q'    "SELECT 1"
+'Y'
+
+# Issue INSERT
+'Q'    "INSERT INTO pgproto_test1 VALUES(1)"
+'Y'
+
+# Issue another SELECT. This should be sent to standby node.
+'Q'    "SELECT 2"
+'Y'
+
+# Issue COMMIT
+'Q'    "COMMIT"
+'Y'
+
+# Issue another SELECT. This should be sent to standby node.
+'Q'    "SELECT 3"
+'Y'
+
+# Start a transaction
+'Q'    "BEGIN"
+'Y'
+
+# Issue another SELECT. This should be sent to standby node.
+'Q'    "SELECT 4"
+'Y'
+
+# Issue COMMIT
+'Q'    "COMMIT"
+'Y'
+
+# DROP test table
+'Q'    "DROP TABLE pgproto_test1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance-simple.data b/src/test/extended-query-test/tests/disable-load-balance-simple.data
new file mode 100644 (file)
index 0000000..830bca9
--- /dev/null
@@ -0,0 +1,57 @@
+# Test for disable_load_balance_on_write feature
+# using simple queries.
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+# Disable load balance in next transaction.
+##disable_load_balance_on_write = 'trans_transaction'
+
+# Create test table
+'Q'    "DROP TABLE IF EXISTS pgproto_test1"
+'Y'
+'Q'    "CREATE TABLE pgproto_test1(i INT)"
+'Y'
+
+# Start a transaction
+'Q'    "BEGIN"
+'Y'
+
+# Issue Parse SELECT. This should be sent to node 1.
+'Q'    "SELECT 1"
+'Y'
+
+# Issue INSERT
+'Q'    "INSERT INTO pgproto_test1 VALUES(1)"
+'Y'
+
+# Issue another SELECT. This should be sent to primary node.
+'Q'    "SELECT 2"
+'Y'
+
+# Issue COMMIT
+'Q'    "COMMIT"
+'Y'
+
+# Issue another SELECT. This should be sent to node 1 because outside a transaction.
+'Q'    "SELECT 3"
+'Y'
+
+# Start a transaction
+'Q'    "BEGIN"
+'Y'
+
+# Issue another SELECT. This should be sent to primary node.
+'Q'    "SELECT 4"
+'Y'
+
+# Issue COMMIT
+'Q'    "COMMIT"
+'Y'
+
+# DROP test table
+'Q'    "DROP TABLE pgproto_test1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance.data b/src/test/extended-query-test/tests/disable-load-balance.data
new file mode 100644 (file)
index 0000000..268e063
--- /dev/null
@@ -0,0 +1,80 @@
+# Test for disable_load_balance_on_write feature.
+#
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+# Disable load balance in next transaction.
+##disable_load_balance_on_write = 'trans_transaction'
+
+# Create test table
+'Q'    "DROP TABLE IF EXISTS pgproto_test1"
+'Y'
+'Q'    "CREATE TABLE pgproto_test1(i INT)"
+'Y'
+
+# Start a transaction
+'P'    ""      "BEGIN" 0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Parse SELECT. This should be sent to node 1.
+'P'    "S1"    "SELECT 1"      0
+
+# Issue INSERT
+'P'    ""      "INSERT INTO pgproto_test1 VALUES(1)"   0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Bind/Execute SELECT. This should be sent to primary node.
+'B'    ""      "S1"    0       0       0
+'E'    ""      0
+
+# Issue another SELECT. This should be sent to primary node.
+'P'    ""      "SELECT 2"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue COMMIT
+'P'    ""      "COMMIT"        0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'S'
+'Y'
+
+# Issue another SELECT. This should be sent to node 1 because outside a transaction.
+'P'    ""      "SELECT 3"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'S'
+'Y'
+
+# Start a transaction
+'P'    ""      "BEGIN" 0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Bind/Execute SELECT. This should be sent to primary node because
+# disable_load_balance_on_write = 'trans_transaction'.
+'B'    ""      "S1"    0       0       0
+'E'    ""      0
+
+# Issue another SELECT. This should be sent to primary node.
+'P'    ""      "SELECT 4"
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue COMMIT
+'P'    ""      "COMMIT"        0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+'C'    'S'     "S1"
+'S'
+'Y'
+
+# DROP test table
+'Q'    "DROP TABLE pgproto_test1"
+'Y'
+
+'X'