pgpool2.git / summary / log / commit / refs
commit e84fe9e5a8d93b7b0e347ee2c7d03a26d2dd7296
Author: Tatsuo Ishii <ishii@sraoss.co.jp>
Date: Thu Sep 28 22:29:28 2023 +0000
Fix Describe() so that it does not abort with portal created by DECLARE.
When DECLARE foo CURSOR FOR is executed, a portal named "foo" is
automatically created by PostgreSQL. As the portal is not managed by
Pgpool-II, "Describe foo" message failed with "unable to execute
Describe. unable to get the bind message" error.
To fix this, make Describe() creates a dummy write query context so
that the describe message is sent to primary (streaming replication
mode) or all nodes (replication/snapshot isolation mode).
Problem analysis by Heather Lapointe.
Discussion: https://www.pgpool.net/pipermail/pgpool-general/2023-September/008995.html
src/protocol/pool_proto_modules.c | 48 ++++++++++++++++++++++++++++++++++-----
1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c
index b1ed1c499..553aebe55 100644
--- a/src/protocol/pool_proto_modules.c
+++ b/src/protocol/pool_proto_modules.c
@@ -112,6 +112,8 @@ static bool multi_statement_query(char *buf);
static void check_prepare(List *parse_tree_list, int len, char *contents);
+static POOL_QUERY_CONTEXT *create_dummy_query_context(void);
+
/*
* This is the workhorse of processing the pg_terminate_backend function to
* make sure that the use of function should not trigger the backend node failover.
@@ -1784,14 +1786,22 @@ Describe(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend,
(errmsg("Describe message from frontend."),
errdetail("portal: \"%s\"", contents + 1)));
msg = pool_get_sent_message('B', contents + 1, POOL_SENT_MESSAGE_CREATED);
- if (!msg)
- ereport(FATAL,
- (return_code(2),
- errmsg("unable to execute Describe"),
- errdetail("unable to get the bind message")));
}
- query_context = msg->query_context;
+ query_context = NULL;
+
+ if (msg)
+ query_context = msg->query_context;
+
+ else if (!msg && *contents == 'P')
+ {
+ /*
+ * It is possible that client wants to use the portal created by
+ * DECLARE CUSOR or pl/pgSQL function. If so, the describe message
+ * should only be sent to primary node.
+ */
+ query_context = create_dummy_query_context();
+ }
if (query_context == NULL)
ereport(FATAL,
@@ -4888,3 +4898,29 @@ check_prepare(List *parse_tree_list, int len, char *contents)
pool_add_sent_message(message); /* add it to the sent message list */
}
}
+
+/*
+ * Create a dummy query context using get_dummy_insert_query_node(). The
+ * query destination is also set. As a side effect, query in progress flag is
+ * set.
+ */
+static
+POOL_QUERY_CONTEXT *create_dummy_query_context(void)
+{
+ POOL_QUERY_CONTEXT *query_context;
+ Node *node;
+ MemoryContext old_context;
+ char *query = "UNKNOWN QUERY";
+
+ query_context = pool_init_query_context();
+ old_context = MemoryContextSwitchTo(query_context->memory_context);
+
+ node = get_dummy_insert_query_node();
+ pool_start_query(query_context, query, strlen(query), node);
+ pool_where_to_send(query_context, query_context->original_query,
+ query_context->parse_tree);
+
+ MemoryContextSwitchTo(old_context);
+
+ return query_context;
+}
[parent: bce1eaa6419d]