Fix hang up and SEGV if Parse message contains a warning statement.
authorYoshiyuki Asaba <y-asaba at pgfoundry.org>
Wed, 25 Jul 2007 06:42:40 +0000 (06:42 +0000)
committerYoshiyuki Asaba <y-asaba at pgfoundry.org>
Wed, 25 Jul 2007 06:42:40 +0000 (06:42 +0000)
  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.

pool_process_query.c

index 5ec0f6eeedb031f1a641a5235ca5e49f3d06e7ae..af4ce1f6a046b6ac1f905ee4a3edc397e2827dd8 100644 (file)
@@ -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
        {