* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2020 PgPool Global Development Group
+ * Copyright (c) 2003-2023 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
}
}
}
+ else if (REPLICATION && query_context->is_multi_statement)
+ {
+ pool_setall_node_to_be_sent(query_context);
+ }
else if (REPLICATION)
{
if (pool_config->load_balance_mode &&
}
/*
- * EXECUTE?
- */
- if (IsA(node, ExecuteStmt))
- {
- POOL_SENT_MESSAGE *msg;
-
- msg = pool_get_sent_message('Q', ((ExecuteStmt *) node)->name, POOL_SENT_MESSAGE_CREATED);
- if (!msg)
- msg = pool_get_sent_message('P', ((ExecuteStmt *) node)->name, POOL_SENT_MESSAGE_CREATED);
- if (msg)
- pool_copy_prep_where(msg->query_context->where_to_send,
- query_context->where_to_send);
- }
-
- /*
- * DEALLOCATE?
+ * DEALLOCATE or EXECUTE?
*/
- else if (IsA(node, DeallocateStmt))
+ if (IsA(node, DeallocateStmt) || IsA(node, ExecuteStmt))
{
where_to_send_deallocate(query_context, node);
}
return POOL_PRIMARY;
}
+/*
+ * Decide where to send given message.
+ * "node" must be a parse tree of either DEALLOCATE or EXECUTE.
+ */
static
void
where_to_send_deallocate(POOL_QUERY_CONTEXT * query_context, Node *node)
{
- DeallocateStmt *d = (DeallocateStmt *) node;
+ DeallocateStmt *d = NULL;
+ ExecuteStmt *e = NULL;
+ char *name;
POOL_SENT_MESSAGE *msg;
+ if (IsA(node, DeallocateStmt))
+ {
+ d = (DeallocateStmt *) node;
+ name = d->name;
+ }
+ else if (IsA(node, ExecuteStmt))
+ {
+ e = (ExecuteStmt *) node;
+ name = e->name;
+ }
+ else
+ {
+ ereport(ERROR,
+ (errmsg("invalid node type for where_to_send_deallocate")));
+ return;
+ }
+
/* DEALLOCATE ALL? */
- if (d->name == NULL)
+ if (d && (name == NULL))
{
+ /* send to all backend node */
pool_setall_node_to_be_sent(query_context);
+ return;
}
+
+ /* ordinary DEALLOCATE or EXECUTE */
else
{
- msg = pool_get_sent_message('Q', d->name, POOL_SENT_MESSAGE_CREATED);
+ /* check if message was created by SQL PREPARE */
+ msg = pool_get_sent_message('Q', name, POOL_SENT_MESSAGE_CREATED);
if (!msg)
- msg = pool_get_sent_message('P', d->name, POOL_SENT_MESSAGE_CREATED);
+ /* message may be created by Parse message */
+ msg = pool_get_sent_message('P', name, POOL_SENT_MESSAGE_CREATED);
if (msg)
{
- /* Inherit same map from PREPARE or PARSE */
+ /* Inherit same map from PREPARE or Parse */
pool_copy_prep_where(msg->query_context->where_to_send,
query_context->where_to_send);
query_context->load_balance_node_id = msg->query_context->load_balance_node_id;
}
else
- /* prepared statement was not found */
- pool_setall_node_to_be_sent(query_context);
+ {
+ /*
+ * prepared statement was not found.
+ * There are two cases when this could happen.
+ * (1) mistakes by client. In this case backend will return ERROR
+ * anyway.
+ * (2) previous query was issued as multi-statement query. e.g.
+ * SELECT 1\;PREPARE foo AS SELECT 1;
+ * In this case pgpool does not know anything about the prepared
+ * statement "foo".
+ */
+ if (SL_MODE)
+ {
+ /*
+ * In streaming replication or logical replication, sent to
+ * primary node only.
+ */
+ pool_set_node_to_be_sent(query_context, PRIMARY_NODE_ID);
+ }
+ else
+ {
+ /*
+ * In other mode, sent to all node.
+ */
+ pool_setall_node_to_be_sent(query_context);
+ }
+ }
}
}
do
echo "=== starting test in \"$mode\" mode ==="
if [ $mode = "n" ];then
- num_tests=5
- else
num_tests=6
+ else
+ num_tests=7
fi
success_count=0
EXECUTE test2;
DEALLOCATE test2;
DEALLOCATE all;
+EOF
+
+ # run test3 multi-statement
+ $PSQL -p 11000 test <<EOF
+SELECT 1\;PREPARE test3 AS SELECT 2;
+DEALLOCATE test3;
EOF
expect1=`fgrep "PREPARE test1" log/pgpool.log | awk '{print substr($0, index($0, "DB node id:"),13)}'`
expect2=`fgrep "PREPARE test2" log/pgpool.log | awk '{print substr($0, index($0, "DB node id:"),13)}'`
+ expect3=`fgrep "PREPARE test3" log/pgpool.log | awk '{print substr($0, index($0, "DB node id:"),13)}'`
#test1 result
echo -n "case 1: PREPARE and EXECUTE with SELECT query..."
echo "failed."
fi
- echo -n "case 6: node1 DEALLOCATE all query..."
if [ $mode = "n" ];then
echo "this test is not applied to mode \"$mode\" and skipped."
else
fi
fi
- echo "In mode \"$mode\" out of $success_count, $num_tests cases succeeded."
+ # DEALLOCATE in multi-statement
+ echo -n "case 6: DEALLOCATE in multi-statement..."
+ result=`fgrep "DEALLOCATE test3" log/pgpool.log | awk '{print substr($0, index($0, "DB node id:"),13)}'`
+ if [ "$expect3" = "$result" ]; then
+ success_count=$(( success_count + 1 ))
+ echo "ok."
+ else
+ echo "failed."
+ fi
./shutdownall