if (select_stmt->intoClause || select_stmt->lockingClause)
return 0;
+ /* non-SELECT query in WITH clause ? */
+ if (select_stmt->withClause)
+ {
+ List *ctes = select_stmt->withClause->ctes;
+ ListCell *cte_item;
+ foreach(cte_item, ctes)
+ {
+ CommonTableExpr *cte = (CommonTableExpr *)lfirst(cte_item);
+ if (!IsA(cte->ctequery, SelectStmt))
+ return false;
+ }
+ }
+
/* '\0' and ';' signify empty query */
return (*sql == 's' || *sql == 'S' || *sql == '(' ||
*sql == 'w' || *sql == 'W' || *sql == 't' || *sql == 'T' ||
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2014 PgPool Global Development Group
+ * Copyright (c) 2003-2015 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
if (pool_has_insertinto_or_locking_clause(node))
return POOL_PRIMARY;
+ /* non-SELECT query in WITH clause ? */
+ if (((SelectStmt *)node)->withClause)
+ {
+ List *ctes = ((SelectStmt *)node)->withClause->ctes;
+ ListCell *cte_item;
+ foreach(cte_item, ctes)
+ {
+ CommonTableExpr *cte = (CommonTableExpr *)lfirst(cte_item);
+ if (!IsA(cte->ctequery, SelectStmt))
+ return POOL_PRIMARY;
+ }
+ }
+
return POOL_EITHER;
}
--- /dev/null
+#!/usr/bin/env bash
+#-------------------------------------------------------------------
+# Test script for bug reported in bug#153
+# CTE queries including DMLs are incorrectly handled.
+
+source $TESTLIBS
+TESTDIR=testdir
+PSQL=$PGBIN/psql
+
+for mode in s r
+do
+ rm -fr $TESTDIR
+ mkdir $TESTDIR
+ cd $TESTDIR
+
+# create test environment
+ echo -n "creating test environment..."
+ $PGPOOL_SETUP -m $mode -n 2 || exit 1
+ echo "done."
+
+ source ./bashrc.ports
+
+ echo "backend_weight0 = 0" >> etc/pgpool.conf
+ echo "backend_weight1 = 1" >> etc/pgpool.conf
+
+ ./startall
+
+ export PGPORT=$PGPOOL_PORT
+
+ wait_for_pgpool_startup
+
+ $PSQL test <<EOF
+CREATE TABLE foo(x serial);
+-- Below should be executed on the primary node in streaming replicatoion mode.
+-- Below should be executed on both nodes in native replicatoion mode.
+WITH r AS (INSERT INTO foo VALUES (default) RETURNING x) SELECT x FROM r;
+
+-- Below should be executed on the primary node in streaming replicatoion mode.
+-- Below should be executed on both nodes in native replicatoion mode.
+WITH t AS (SELECT nextval('foo_x_seq')) SELECT * FROM t;
+
+-- Below should be executed on node 1.
+WITH s AS (SELECT 1) SELECT * FROM s;
+EOF
+
+# check if read query is load balanced.
+ fgrep "SELECT 1" log/pgpool.log |grep "DB node id: 1">/dev/null 2>&1
+ if [ $? != 0 ];then
+ # expected result not found
+ echo 'fail: WITH s AS (SELECT 1) SELECT * FROM s;'
+ ./shutdownall
+ exit 1
+ fi
+
+ if [ $mode = "r" ];then
+ fgrep "SELECT 1" log/pgpool.log |grep "DB node id: 0">/dev/null 2>&1
+ if [ $? = 0 ];then
+ # expected result not found
+ echo 'fail: WITH s AS (SELECT 1) SELECT * FROM s;'
+ ./shutdownall
+ exit 1
+ fi
+ fi
+
+ echo ok: read query load balance works.
+
+# check if data modifying WITH worked
+ fgrep "WITH r AS" log/pgpool.log |grep "DB node id: 0">/dev/null 2>&1
+ if [ $? != 0 ];then
+ # expected result not found
+ echo 'fail: data modifying WITH.'
+ ./shutdownall
+ exit 1
+ fi
+
+ if [ $mode = "r" ];then
+ fgrep "WITH r AS" log/pgpool.log |grep "DB node id: 1">/dev/null 2>&1
+ if [ $? != 0 ];then
+ # expected result not found
+ echo 'fail: data modifying WITH in replication mode.'
+ ./shutdownall
+ exit 1
+ fi
+ fi
+
+# check if WITH SELECT including data modifying function call worked.
+ fgrep "WITH t AS" log/pgpool.log |grep "DB node id: 0">/dev/null 2>&1
+ if [ $? != 0 ];then
+ # expected result not found
+ echo 'fail: WITH SELECT including data modifying function call.'
+ ./shutdownall
+ exit 1
+ fi
+
+ if [ $mode = "r" ];then
+ fgrep "WITH t AS" log/pgpool.log |grep "DB node id: 1">/dev/null 2>&1
+ if [ $? != 0 ];then
+ # expected result not found
+ echo 'fail: WITH SELECT including data modifying function call.'
+ ./shutdownall
+ exit 1
+ fi
+ fi
+ ./shutdownall
+
+ cd ..
+done
+
+exit 0