pgpool2.git / summary / log / commit / refs
commit 52fdcfe274e82da6923dc18afc67ac7cb8ff8005
Author: Toshihiro Kitagawa <kitagawa at sraoss.co.jp>
Date: Tue Oct 12 11:39:37 2010 +0000
Fix portal handling in extended query protocol.
Now, prepared statements and portals are closed separately.
This issue is possible to reappear by a program using setFetchSize(1) of JDBC.
pool_proto_modules.c | 8 +++++---
pool_session_context.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++--
pool_session_context.h | 1 +
3 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/pool_proto_modules.c b/pool_proto_modules.c
index b989690bd..24d4851a3 100644
--- a/pool_proto_modules.c
+++ b/pool_proto_modules.c
@@ -978,6 +978,7 @@ POOL_STATUS Describe(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
return POOL_CONTINUE;
}
+
POOL_STATUS Close(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
int len, char *contents)
{
@@ -1005,6 +1006,7 @@ POOL_STATUS Close(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
}
session_context->pending_pstmt = pstmt;
+ query_context = pstmt->qctxt;
}
/* Portal */
else if (*contents == 'P')
@@ -1017,6 +1019,7 @@ POOL_STATUS Close(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
}
session_context->pending_portal = portal;
+ query_context = portal->qctxt;
}
else
{
@@ -1024,15 +1027,14 @@ POOL_STATUS Close(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
return POOL_END;
}
- query_context = pstmt->qctxt;
if (query_context == NULL)
{
pool_error("Close: cannot get query context");
return POOL_END;
}
- pool_where_to_send(query_context, query_context->original_query,
- query_context->parse_tree);
+ session_context->query_context = query_context;
+ /* pool_where_to_send(query_context, query_context->original_query, query_context->parse_tree); */
pool_debug("Close: waiting for master completing the query");
if (pool_send_and_wait(query_context, contents, len, 1, MASTER_NODE_ID, "C")
diff --git a/pool_session_context.c b/pool_session_context.c
index 2336158f4..540b9933d 100644
--- a/pool_session_context.c
+++ b/pool_session_context.c
@@ -33,6 +33,8 @@ static POOL_SESSION_CONTEXT *session_context = NULL;
static void init_prepared_statement_list(void);
static void init_portal_list(void);
+static bool can_prepared_statement_destroy(POOL_QUERY_CONTEXT *qc);
+static bool can_portal_destroy(POOL_QUERY_CONTEXT *qc);
/*
* Initialize per session context
@@ -368,6 +370,8 @@ static void pool_remove_portal_by_portal_name(const char *name)
{
if (strcmp(plist->portals[i]->name, name) == 0)
{
+ if (can_portal_destroy(plist->portals[i]->qctxt))
+ pool_query_context_destroy(plist->portals[i]->qctxt);
pool_memory_free(session_context->memory_context, plist->portals[i]);
break;
}
@@ -389,6 +393,7 @@ static void pool_remove_portal_by_portal_name(const char *name)
* Remove portals by prepared statement name
* prepared statement : portal = 1 : N
*/
+#ifdef NOT_USED
static void pool_remove_portal_by_pstmt_name(const char *name)
{
int i;
@@ -413,6 +418,7 @@ static void pool_remove_portal_by_pstmt_name(const char *name)
pool_remove_portal_by_portal_name(plist->portals[i]->name);
}
}
+#endif
/*
* Remove a prepared statement by prepared statement name
@@ -451,7 +457,8 @@ void pool_remove_prepared_statement_by_pstmt_name(const char *name)
{
if (strcmp(pslist->pstmts[i]->name, name) == 0)
{
- pool_query_context_destroy(pslist->pstmts[i]->qctxt);
+ if (can_prepared_statement_destroy(pslist->pstmts[i]->qctxt))
+ pool_query_context_destroy(pslist->pstmts[i]->qctxt);
pool_memory_free(session_context->memory_context, pslist->pstmts[i]);
break;
}
@@ -472,7 +479,11 @@ void pool_remove_prepared_statement_by_pstmt_name(const char *name)
}
pslist->size--;
- pool_remove_portal_by_pstmt_name(name);
+ /*
+ * prepared statements and portals are closed separately
+ * by a frontend.
+ */
+ /* pool_remove_portal_by_pstmt_name(name); */
if (in_progress)
pool_set_query_in_progress();
@@ -639,6 +650,7 @@ Portal *pool_create_portal(const char *name, int num_tsparams, PreparedStatement
portal->name = pool_memory_strdup(session_context->memory_context, name);
portal->num_tsparams = num_tsparams;
portal->pstmt = pstmt;
+ portal->qctxt = pstmt->qctxt;
return portal;
}
@@ -1137,3 +1149,41 @@ static void init_portal_list(void)
exit(1);
}
}
+
+static bool can_prepared_statement_destroy(POOL_QUERY_CONTEXT *qc)
+{
+ int i;
+ PortalList *plist;
+
+ plist = &session_context->portal_list;
+
+ for (i = 0; i < plist->size; i++)
+ {
+ if (plist->portals[i]->qctxt == qc)
+ {
+ pool_debug("can_prepared_statement_destroy: query context is still used.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool can_portal_destroy(POOL_QUERY_CONTEXT *qc)
+{
+ int i;
+ PreparedStatementList *pslist;
+
+ pslist = &session_context->pstmt_list;
+
+ for (i = 0; i < pslist->size; i++)
+ {
+ if (pslist->pstmts[i]->qctxt == qc)
+ {
+ pool_debug("can_portal_destroy: query context is still used.");
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/pool_session_context.h b/pool_session_context.h
index f90705346..3c2fb0223 100644
--- a/pool_session_context.h
+++ b/pool_session_context.h
@@ -61,6 +61,7 @@ typedef struct {
char *name; /* portal name */
int num_tsparams;
PreparedStatement *pstmt;
+ POOL_QUERY_CONTEXT *qctxt;
} Portal;
/*
[parent: 41061153c616]