feature: Disable load balance after a SELECT having functions specified in black...
authorBo Peng <pengbo@sraoss.co.jp>
Mon, 1 Jul 2019 03:50:49 +0000 (12:50 +0900)
committerBo Peng <pengbo@sraoss.co.jp>
Mon, 1 Jul 2019 03:50:49 +0000 (12:50 +0900)
In Pgpool-II 4.0 or earlier, if we set "disable_load_balance_on_write = transaction",
when a write query is issued inside an explicit truncation,
subsequent queries should be sent to primary only until the
end of this transactionin in order to avoid the replication
delay.

However, the SELECTs having write functions specified in black_function_list
are not regarded as a write query and the subsequent read queries are still load balanced.

This commit will disable load balance after a SELECT having functions
specified in black/white function list.

21 files changed:
doc.ja/src/sgml/loadbalance.sgml
doc/src/sgml/loadbalance.sgml
src/protocol/pool_proto_modules.c
src/test/extended-query-test/expected/disable-load-balance-always-black-function.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance-default-black-function.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance-off-black-function.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance-simple-black-function.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance-trans-black-function.data [new file with mode: 0644]
src/test/extended-query-test/expected/disable-load-balance-white-function.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-always-black-function.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-default-black-function.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-off-black-function.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-simple-black-function.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-trans-black-function.data [new file with mode: 0644]
src/test/extended-query-test/extra_scripts/disable-load-balance-white-function.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-always-black-function.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-default-black-function.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-off-black-function.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-simple-black-function.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-trans-black-function.data [new file with mode: 0644]
src/test/extended-query-test/tests/disable-load-balance-white-function.data [new file with mode: 0644]

index 59eae8eeb3c9bef40302d6563ed2221d10b6a579..cefb8c09c7dde07bddf521458cad9584e784810c 100644 (file)
 <!--
               transaction has not issued a write query yet (until a write
               query is issued, load balance is possible. Here "write query"
-              means non SELECT DML or DDL. SELECTs having write functions as
-              specified in black or white function list is not regarded as
-              a write query. This may be changed in the future.)
+              means non SELECT DML or DDL. <EMPHASIS>Before <productname>Pgpool-II</> 4.1</>,
+              SELECTs having write functions as specified in black or
+              white function list is not regarded as a write query.)
 -->
 トランザクション内で更新を伴うクエリが実行されていない
 (更新を伴うクエリが実行されるまでは負荷分散されます。
 ここで「更新を伴うクエリ」とは、SELECT以外のDDLやDMLを指します。
-black/white function listで指定される更新関数を含むSELECTは更新を伴うクエリとは見なされません。
\81\93ã\81®ä»\95æ§\98ã\81¯å°\86æ\9d¥å¤\89æ\9b´ã\81\95ã\82\8cã\82\8bå\8f¯è\83½æ\80§ã\81\8cã\81\82ã\82\8aã\81¾ã\81\99)
+<EMPHASIS><productname>Pgpool-II</>4.1以前</>のバージョンでは、black/white function list
\81§æ\8c\87å®\9aã\81\95ã\82\8cã\82\8bæ\9b´æ\96°é\96¢æ\95°ã\82\92å\90«ã\82\80SELECTã\81¯æ\9b´æ\96°ã\82\92ä¼´ã\81\86ã\82¯ã\82¨ã\83ªã\81¨ã\81¯è¦\8bã\81ªã\81\95ã\82\8cã\81¾ã\81\9bã\82\93ã\80\82)
               </para>
             </listitem>
             <listitem>
index ad49f3779def722ddfeb20134a9f23223763d41b..aa03bd85ee8c301691a1d61c9d6871ebc17c003d 100644 (file)
@@ -76,9 +76,9 @@
               <para>
               transaction has not issued a write query yet (until a write
               query is issued, load balance is possible. Here "write query"
-              means non SELECT DML or DDL. SELECTs having write functions as
-              specified in black or white function list is not regarded as
-              a write query. This may be changed in the future.)
+              means non SELECT DML or DDL. <EMPHASIS>Before <productname>Pgpool-II</> 4.1</>,
+              SELECTs having write functions as specified in black or
+              white function list is not regarded as a write query.)
               </para>
             </listitem>
             <listitem>
index b6d985d3e1fdc233be27436e8abd52804121caef..ac22f169e64406df63cf36acbf53c45136f349a7 100644 (file)
@@ -966,8 +966,9 @@ Execute(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend,
                /*
                 * Take care of "writing transaction" flag.
                 */
-               if (!is_select_query(node, query) && !is_start_transaction_query(node) &&
-                       !is_commit_or_rollback_query(node))
+               if ((!is_select_query(node, query) || pool_has_function_call(node)) &&
+                        !is_start_transaction_query(node) &&
+                        !is_commit_or_rollback_query(node))
                {
                        ereport(DEBUG1,
                                        (errmsg("Execute: TSTATE:%c",
@@ -3959,7 +3960,7 @@ pool_at_command_success(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backe
                close_standby_transactions(frontend, backend);
        }
 
-       else if (!is_select_query(node, query))
+       else if (!is_select_query(node, query) || pool_has_function_call(node))
        {
                /*
                 * If the query was not READ SELECT, and we are in an explicit
diff --git a/src/test/extended-query-test/expected/disable-load-balance-always-black-function.data b/src/test/extended-query-test/expected/disable-load-balance-always-black-function.data
new file mode 100644 (file)
index 0000000..3924da9
--- /dev/null
@@ -0,0 +1,83 @@
+FE=> Query (query="DROP FUNCTION IF EXISTS f1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M function f1() does not exist, skipping F dropcmds.c L 483 R does_not_exist_skipping )
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Query (query="CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL")
+<= BE CommandComplete(CREATE FUNCTION)
+<= 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="SELECT f1(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 DataRow
+<= BE CommandComplete(SELECT 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 FUNCTION f1")
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance-default-black-function.data b/src/test/extended-query-test/expected/disable-load-balance-default-black-function.data
new file mode 100644 (file)
index 0000000..3924da9
--- /dev/null
@@ -0,0 +1,83 @@
+FE=> Query (query="DROP FUNCTION IF EXISTS f1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M function f1() does not exist, skipping F dropcmds.c L 483 R does_not_exist_skipping )
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Query (query="CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL")
+<= BE CommandComplete(CREATE FUNCTION)
+<= 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="SELECT f1(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 DataRow
+<= BE CommandComplete(SELECT 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 FUNCTION f1")
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance-off-black-function.data b/src/test/extended-query-test/expected/disable-load-balance-off-black-function.data
new file mode 100644 (file)
index 0000000..3924da9
--- /dev/null
@@ -0,0 +1,83 @@
+FE=> Query (query="DROP FUNCTION IF EXISTS f1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M function f1() does not exist, skipping F dropcmds.c L 483 R does_not_exist_skipping )
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Query (query="CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL")
+<= BE CommandComplete(CREATE FUNCTION)
+<= 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="SELECT f1(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 DataRow
+<= BE CommandComplete(SELECT 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 FUNCTION f1")
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance-simple-black-function.data b/src/test/extended-query-test/expected/disable-load-balance-simple-black-function.data
new file mode 100644 (file)
index 0000000..1e7ebfe
--- /dev/null
@@ -0,0 +1,48 @@
+FE=> Query (query="DROP FUNCTION IF EXISTS f1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M function f1() does not exist, skipping F dropcmds.c L 483 R does_not_exist_skipping )
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Query (query="CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL")
+<= BE CommandComplete(CREATE FUNCTION)
+<= 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="SELECT f1(1)")
+<= BE RowDescription
+<= BE DataRow
+<= BE CommandComplete(SELECT 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 FUNCTION f1")
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance-trans-black-function.data b/src/test/extended-query-test/expected/disable-load-balance-trans-black-function.data
new file mode 100644 (file)
index 0000000..3924da9
--- /dev/null
@@ -0,0 +1,83 @@
+FE=> Query (query="DROP FUNCTION IF EXISTS f1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M function f1() does not exist, skipping F dropcmds.c L 483 R does_not_exist_skipping )
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Query (query="CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL")
+<= BE CommandComplete(CREATE FUNCTION)
+<= 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="SELECT f1(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 DataRow
+<= BE CommandComplete(SELECT 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 FUNCTION f1")
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/expected/disable-load-balance-white-function.data b/src/test/extended-query-test/expected/disable-load-balance-white-function.data
new file mode 100644 (file)
index 0000000..3924da9
--- /dev/null
@@ -0,0 +1,83 @@
+FE=> Query (query="DROP FUNCTION IF EXISTS f1")
+<= BE NoticeResponse(S NOTICE V NOTICE C 00000 M function f1() does not exist, skipping F dropcmds.c L 483 R does_not_exist_skipping )
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Query (query="CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL")
+<= BE CommandComplete(CREATE FUNCTION)
+<= 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="SELECT f1(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 DataRow
+<= BE CommandComplete(SELECT 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 FUNCTION f1")
+<= BE CommandComplete(DROP FUNCTION)
+<= BE ReadyForQuery(I)
+FE=> Terminate
diff --git a/src/test/extended-query-test/extra_scripts/disable-load-balance-always-black-function.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-always-black-function.data
new file mode 100644 (file)
index 0000000..85c833b
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+# expected results: Create: 0 Parse: 1 Parse: 0 Execute: 0 Parse: 0 Execute: 0
+# Parse: 0 Execute: 0 Parse: 0 Execute: 0 Parse: 0 Execute: 0
+set 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-black-function.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-default-black-function.data
new file mode 100644 (file)
index 0000000..2cfb397
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# expected results: Create: 0 Parse: 1 Parse: 0 Execute: 0 Parse: 0 Execute: 0 Parse: 0 Execute: 0
+# Parse: 1 Execute: 1
+# Execute: 0 Parse: 0 Execute: 0
+set 0 1 0 0 0 0 0 0 1 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-off-black-function.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-off-black-function.data
new file mode 100644 (file)
index 0000000..4e3093b
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# expected results: Create: 0 Parse: 1 Parse: 0 Execute: 0 Parse: 1 Execute: 1 Parse: 1 Execute: 1
+# Parse: 1 Execute: 1
+# Execute: 1 Parse: 1 Execute: 1
+set 0 1 0 0 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-black-function.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-simple-black-function.data
new file mode 100644 (file)
index 0000000..de90918
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# expected results: CREATE: 0 SELECT: 1 SELECT: 0 SELECT: 0 SELECT: 1 SELECT: 1
+set 0 1 0 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-trans-black-function.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-trans-black-function.data
new file mode 100644 (file)
index 0000000..8f075cc
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# expected results: Create: 0 Parse: 1 Parse: 0 Execute: 0 Parse: 0 Execute: 0 Parse: 0 Execute: 0
+# Parse: 1 Execute: 1
+# Execute: 0 Parse: 0 Execute: 0
+set 0 1 0 0 0 0 0 0 1 1 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-white-function.data b/src/test/extended-query-test/extra_scripts/disable-load-balance-white-function.data
new file mode 100644 (file)
index 0000000..10b46d2
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# expected results: Create: 0 Parse: 1 parse: 1 Execute: 1 Parse: 1 Execute: 1 Parse: 1 Execute: 1
+# Parse: 1 Execute: 1
+# Parse: 1 Execute: 1 Parse: 1 Execute: 1
+set 0 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/tests/disable-load-balance-always-black-function.data b/src/test/extended-query-test/tests/disable-load-balance-always-black-function.data
new file mode 100644 (file)
index 0000000..c943ba1
--- /dev/null
@@ -0,0 +1,85 @@
+# Test for load_balance_on_write function feature. disable_load_balance_on_write = 'always'
+#
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+##black_function_list = 'f1'
+
+# disable_load_balance_on_write = 'always'
+# Disable load balance after a WRITE function is issued.
+
+## disable_load_balance_on_write = 'always'
+
+# Create test white function
+'Q'    "DROP FUNCTION IF EXISTS f1"
+'Y'
+'Q'    "CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL"
+'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
+
+# Execute function f1. This should be sent to primary node.
+'P'    ""      "SELECT f1(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 primary 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'
+
+
+# DROP test table
+'Q'    "DROP FUNCTION f1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance-default-black-function.data b/src/test/extended-query-test/tests/disable-load-balance-default-black-function.data
new file mode 100644 (file)
index 0000000..7a94243
--- /dev/null
@@ -0,0 +1,83 @@
+# Test for load_balance_on_write function feature. disable_load_balance_on_write = 'transaction'
+#
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+##black_function_list = 'f1'
+
+# Disable load balance in current transaction only. (disable_load_balance_on_write = 'transaction')
+# (default behavior)
+
+# Create test white function
+'Q'    "DROP FUNCTION IF EXISTS f1"
+'Y'
+'Q'    "CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL"
+'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
+
+# Execute function f1. This should be sent to primary node.
+'P'    ""      "SELECT f1(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 FUNCTION f1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance-off-black-function.data b/src/test/extended-query-test/tests/disable-load-balance-off-black-function.data
new file mode 100644 (file)
index 0000000..d57adf6
--- /dev/null
@@ -0,0 +1,86 @@
+# Test for load_balance_on_write function feature. disable_load_balance_on_write = 'off'
+#
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+##black_function_list = 'f1'
+
+# disable_load_balance_on_write = 'off'
+# Don't disable load balance even if a WRITE function is issued.
+
+## disable_load_balance_on_write = 'off'
+
+
+# Create test white function
+'Q'    "DROP FUNCTION IF EXISTS f1"
+'Y'
+'Q'    "CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL"
+'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
+
+# Execute function f1. This should be sent to primary node.
+'P'    ""      "SELECT f1(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'
+
+
+# DROP test table
+'Q'    "DROP FUNCTION f1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance-simple-black-function.data b/src/test/extended-query-test/tests/disable-load-balance-simple-black-function.data
new file mode 100644 (file)
index 0000000..176f8c9
--- /dev/null
@@ -0,0 +1,59 @@
+# Test for disable_load_balance_on_write on write function feature
+# using simple queries.
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+##black_function_list = 'f1'
+
+# Disable load balance in current transaction only. (disable_load_balance_on_write = 'transaction')
+# (default behavior)
+
+# Create test white function
+'Q'    "DROP FUNCTION IF EXISTS f1"
+'Y'
+'Q'    "CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL"
+'Y'
+
+# Start a transaction
+'Q'    "BEGIN"
+'Y'
+
+# Issue Parse SELECT. This should be sent to node 1.
+'Q'    "SELECT 1"
+'Y'
+
+# Issue INSERT
+'Q'    "SELECT f1(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 standby node.
+'Q'    "SELECT 4"
+'Y'
+
+# Issue COMMIT
+'Q'    "COMMIT"
+'Y'
+
+# DROP test table
+'Q'    "DROP FUNCTION f1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance-trans-black-function.data b/src/test/extended-query-test/tests/disable-load-balance-trans-black-function.data
new file mode 100644 (file)
index 0000000..f353e6e
--- /dev/null
@@ -0,0 +1,86 @@
+# Test for load_balance_on_write function feature. disable_load_balance_on_write = 'trans_transaction'
+#
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+##black_function_list = 'f1'
+
+# disable_load_balance_on_write = 'trans_transaction'
+# Disable load balance in next transaction
+
+## disable_load_balance_on_write = 'trans_transaction'
+
+# Create test white function
+'Q'    "DROP FUNCTION IF EXISTS f1"
+'Y'
+'Q'    "CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL"
+'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
+
+# Execute function f1. This should be sent to primary node.
+'P'    ""      "SELECT f1(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 FUNCTION f1"
+'Y'
+
+'X'
diff --git a/src/test/extended-query-test/tests/disable-load-balance-white-function.data b/src/test/extended-query-test/tests/disable-load-balance-white-function.data
new file mode 100644 (file)
index 0000000..17d493c
--- /dev/null
@@ -0,0 +1,81 @@
+# Test for load_balance_on_read function feature.
+#
+
+# Force load balance node to 1.
+##backend_weight0 = 0
+##backend_weight1 = 1
+
+# Disable load balance in current transaction only. (disable_load_balance_on_write = 'transaction')
+# (default behavior)
+
+# Create test white function
+'Q'    "DROP FUNCTION IF EXISTS f1"
+'Y'
+'Q'    "CREATE FUNCTION f1(INTEGER) returns INTEGER AS 'SELECT $1' LANGUAGE SQL"
+'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
+
+# Execute function f1. This should be sent to node 1.
+'P'    ""      "SELECT f1(1)"  0
+'B'    ""      ""      0       0       0
+'E'    ""      0
+
+# Issue Bind/Execute SELECT. This should be sent to node 1.
+'B'    ""      "S1"    0       0       0
+'E'    ""      0
+
+# Issue another SELECT. This should be sent to node 1.
+'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 FUNCTION f1"
+'Y'
+
+'X'