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]