diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index ec62550e38..b530c51ccd 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -2109,19 +2109,19 @@ PQgetResult(PGconn *conn) break; case PGASYNC_READY: + res = pqPrepareAsyncResult(conn); /* - * For any query type other than simple query protocol, we advance - * the command queue here. This is because for simple query - * protocol we can get the READY state multiple times before the - * command is actually complete, since the command string can - * contain many queries. In simple query protocol, the queue - * advance is done by fe-protocol3 when it receives ReadyForQuery. + * When an error has occurred, we consume one command from the + * queue for each result we return. (Normally, the command would + * be consumed as each result is read from the server.) */ if (conn->cmd_queue_head && - conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE) + (conn->error_result || + (conn->result != NULL && + conn->result->resultStatus == PGRES_FATAL_ERROR))) pqCommandQueueAdvance(conn); - res = pqPrepareAsyncResult(conn); + if (conn->pipelineStatus != PQ_PIPELINE_OFF) { /* diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c index 8ab6a88416..2ed74aa0f1 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -205,6 +205,10 @@ pqParseInput3(PGconn *conn) pqSaveErrorResult(conn); } } + if (conn->cmd_queue_head && + conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE) + pqCommandQueueAdvance(conn); + if (conn->result) strlcpy(conn->result->cmdStatus, conn->workBuffer.data, CMDSTATUS_LEN); @@ -231,6 +235,7 @@ pqParseInput3(PGconn *conn) else { conn->pipelineStatus = PQ_PIPELINE_ON; + pqCommandQueueAdvance(conn); conn->asyncStatus = PGASYNC_READY; } } @@ -257,6 +262,7 @@ pqParseInput3(PGconn *conn) pqSaveErrorResult(conn); } } + /* XXX should we advance the command queue here? */ conn->asyncStatus = PGASYNC_READY; break; case '1': /* Parse Complete */ @@ -274,6 +280,7 @@ pqParseInput3(PGconn *conn) pqSaveErrorResult(conn); } } + pqCommandQueueAdvance(conn); conn->asyncStatus = PGASYNC_READY; } break; @@ -324,6 +331,10 @@ pqParseInput3(PGconn *conn) * really possible with the current backend.) We stop * parsing until the application accepts the current * result. + * + * Note that we must have already read one 'T' message + * previously for the same command, so we do not + * advance the command queue here. */ conn->asyncStatus = PGASYNC_READY; return; @@ -355,6 +366,7 @@ pqParseInput3(PGconn *conn) } } conn->asyncStatus = PGASYNC_READY; + pqCommandQueueAdvance(conn); } break; case 't': /* Parameter Description */ @@ -593,14 +605,20 @@ getRowDescriptions(PGconn *conn, int msgLength) /* * If we're doing a Describe, we're done, and ready to pass the result * back to the client. + * + * XXX this coding here is a bit suspicious ... */ - if ((!conn->cmd_queue_head) || - (conn->cmd_queue_head && - conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE)) + if (!conn->cmd_queue_head) { conn->asyncStatus = PGASYNC_READY; return 0; } + else if (conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE) + { + conn->asyncStatus = PGASYNC_READY; + pqCommandQueueAdvance(conn); + return 0; + } /* * We could perform additional setup for the new result set here, but for