summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoshiyuki Asaba2007-07-25 06:42:40 +0000
committerYoshiyuki Asaba2007-07-25 06:42:40 +0000
commit545a05a3d282d507b22fbffe07eefd9353058859 (patch)
treefee8511ef08b14ebf6d39cd5dcf4ccc13f4b92ca
parent27ddc1b744f139f9ef9e698e1d2eef5b2999a5df (diff)
Fix hang up and SEGV if Parse message contains a warning statement.
SELECT '\''; WARNING: nonstandard use of \' in a string literal If pgpool receives a warning message that is NoticeMessage('N') under the extended query protocol, it reads a next message.
-rw-r--r--pool_process_query.c87
1 files changed, 57 insertions, 30 deletions
diff --git a/pool_process_query.c b/pool_process_query.c
index 5ec0f6e..af4ce1f 100644
--- a/pool_process_query.c
+++ b/pool_process_query.c
@@ -841,30 +841,33 @@ static POOL_STATUS Execute(POOL_CONNECTION *frontend,
stmt = lookup_prepared_statement_by_portal(&prepared_list, string);
- /* load balance trick */
- if (stmt && load_balance_enabled(backend, stmt->prepared_string))
- start_load_balance(backend);
- else if (MASTER_SLAVE)
+ if (stmt)
{
- master_slave_was_enabled = 1;
- MASTER_SLAVE = 0;
- master_slave_dml = 1;
- }
- else if (REPLICATION && !pool_config.replicate_select && is_select_query(stmt->prepared_string) && !is_sequence_query(stmt->prepared_string))
- {
- int i;
-
- /* save backend connection slots */
- for (i=0;i<backend->num;i++)
+ /* load balance trick */
+ if (stmt && load_balance_enabled(backend, stmt->prepared_string))
+ start_load_balance(backend);
+ else if (MASTER_SLAVE)
{
- slots[i] = backend->slots[i];
+ master_slave_was_enabled = 1;
+ MASTER_SLAVE = 0;
+ master_slave_dml = 1;
}
+ else if (REPLICATION && !pool_config.replicate_select && is_select_query(stmt->prepared_string) && !is_sequence_query(stmt->prepared_string))
+ {
+ int i;
- /* send query to master only. */
- replication_was_enabled = 1;
- REPLICATION = 0;
- in_load_balance = 1;
- select_in_transaction = 1;
+ /* save backend connection slots */
+ for (i=0;i<backend->num;i++)
+ {
+ slots[i] = backend->slots[i];
+ }
+
+ /* send query to master only. */
+ replication_was_enabled = 1;
+ REPLICATION = 0;
+ in_load_balance = 1;
+ select_in_transaction = 1;
+ }
}
for (i = 0;i < backend->num;i++)
@@ -2549,8 +2552,8 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C
/*
* Check if packet kind == 'C'(Command complete), '1'(Parse
- * complete), '3'(Close complete). If so, then register or unregister
- * pending prepared statement.
+ * complete), '3'(Close complete). If so, then register or
+ * unregister pending prepared statement.
*/
if ((kind == 'C' || kind == '1' || kind == '3') &&
pending_function && pending_prepared_stmt)
@@ -2560,8 +2563,15 @@ POOL_STATUS SimpleForwardToFrontend(char kind, POOL_CONNECTION *frontend, POOL_C
else if (kind == 'C' && select_in_transaction)
select_in_transaction = 0;
- pending_function = NULL;
- pending_prepared_stmt = NULL;
+ /*
+ * Remove a pending function if a received message is not
+ * NoticeResponse.
+ */
+ if (kind != 'N')
+ {
+ pending_function = NULL;
+ pending_prepared_stmt = NULL;
+ }
status = pool_read(MASTER(backend), &len, sizeof(len));
if (status < 0)
@@ -2901,6 +2911,12 @@ POOL_STATUS SimpleForwardToBackend(char kind, POOL_CONNECTION *frontend, POOL_CO
break;
}
+
+ /*
+ * Describe message with a portal name receive two messages.
+ * 1. ParameterDescription
+ * 2. RowDescriptions or NoData
+ */
if (kind == 'D' && *p == 'S')
{
kind1 = pool_read_kind(backend);
@@ -2913,14 +2929,25 @@ POOL_STATUS SimpleForwardToBackend(char kind, POOL_CONNECTION *frontend, POOL_CO
pool_flush(frontend);
}
- kind1 = pool_read_kind(backend);
- if (kind1 < 0)
+ for (;;)
{
- pool_error("SimpleForwardToBackend: pool_read_kind error");
- return POOL_ERROR;
+ kind1 = pool_read_kind(backend);
+ if (kind1 < 0)
+ {
+ pool_error("SimpleForwardToBackend: pool_read_kind error");
+ return POOL_ERROR;
+ }
+ SimpleForwardToFrontend(kind1, frontend, backend);
+ if (pool_flush(frontend) < 0)
+ return POOL_ERROR;
+
+ /*
+ * If warning or log messages are received, we must read
+ * one message from backend.
+ */
+ if (kind1 != 'N') /* Notice Message */
+ break;
}
- SimpleForwardToFrontend(kind1, frontend, backend);
- return pool_flush(frontend);
}
else
{