@ -2112,19 +2112,12 @@ PQgetResult(PGconn *conn)
break ;
break ;
case PGASYNC_READY :
case PGASYNC_READY :
/*
* 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 .
*/
if ( conn - > cmd_queue_head & &
conn - > cmd_queue_head - > queryclass ! = PGQUERY_SIMPLE )
pqCommandQueueAdvance ( conn ) ;
res = pqPrepareAsyncResult ( conn ) ;
res = pqPrepareAsyncResult ( conn ) ;
/* Advance the queue as appropriate */
pqCommandQueueAdvance ( conn , false ,
res - > resultStatus = = PGRES_PIPELINE_SYNC ) ;
if ( conn - > pipelineStatus ! = PQ_PIPELINE_OFF )
if ( conn - > pipelineStatus ! = PQ_PIPELINE_OFF )
{
{
/*
/*
@ -3007,18 +3000,44 @@ PQexitPipelineMode(PGconn *conn)
/*
/*
* pqCommandQueueAdvance
* pqCommandQueueAdvance
* Remove one query from the command queue , when we receive
* Remove one query from the command queue , if appropriate .
* all results from the server that pertain to it .
*
* If we have received all results corresponding to the head element
* in the command queue , remove it .
*
* In simple query protocol we must not advance the command queue until the
* ReadyForQuery message has been received . This is because in simple mode a
* command can have multiple queries , and we must process result for all of
* them before moving on to the next command .
*
* Another consideration is synchronization during error processing in
* extended query protocol : we refuse to advance the queue past a SYNC queue
* element , unless the result we ' ve received is also a SYNC . In particular
* this protects us from advancing when an error is received at an
* inappropriate moment .
*/
*/
void
void
pqCommandQueueAdvance ( PGconn * conn )
pqCommandQueueAdvance ( PGconn * conn , bool isReadyForQuery , bool gotSync )
{
{
PGcmdQueueEntry * prevquery ;
PGcmdQueueEntry * prevquery ;
if ( conn - > cmd_queue_head = = NULL )
if ( conn - > cmd_queue_head = = NULL )
return ;
return ;
/* delink from queue */
/*
* If processing a query of simple query protocol , we only advance the
* queue when we receive the ReadyForQuery message for it .
*/
if ( conn - > cmd_queue_head - > queryclass = = PGQUERY_SIMPLE & & ! isReadyForQuery )
return ;
/*
* If we ' re waiting for a SYNC , don ' t advance the queue until we get one .
*/
if ( conn - > cmd_queue_head - > queryclass = = PGQUERY_SYNC & & ! gotSync )
return ;
/* delink element from queue */
prevquery = conn - > cmd_queue_head ;
prevquery = conn - > cmd_queue_head ;
conn - > cmd_queue_head = conn - > cmd_queue_head - > next ;
conn - > cmd_queue_head = conn - > cmd_queue_head - > next ;
@ -3026,7 +3045,7 @@ pqCommandQueueAdvance(PGconn *conn)
if ( conn - > cmd_queue_head = = NULL )
if ( conn - > cmd_queue_head = = NULL )
conn - > cmd_queue_tail = NULL ;
conn - > cmd_queue_tail = NULL ;
/* and make i t recyclable */
/* and make the queue elemen t recyclable */
prevquery - > next = NULL ;
prevquery - > next = NULL ;
pqRecycleCmdQueueEntry ( conn , prevquery ) ;
pqRecycleCmdQueueEntry ( conn , prevquery ) ;
}
}