case 'E': /* ErrorResponse */
HandleError(combiner, msg, msg_len, conn);
add_error_message(conn, combiner->errorMessage);
+ /*
+ * In case the remote node was running an extended query
+ * protocol and reported an error, it will keep ignoring all
+ * subsequent commands until it sees a SYNC message. So make
+ * sure that we send down SYNC even before sending a ROLLBACK
+ * command
+ */
+ if (conn->in_extended_query)
+ conn->needSync = true;
return RESPONSE_ERROR;
case 'A': /* NotificationResponse */
case 'N': /* NoticeResponse */
if (conn->state != DN_CONNECTION_STATE_IDLE)
BufferConnection(conn);
+ /*
+ * If the remote session was running extended query protocol when
+ * it failed, it will expect a SYNC message before it accepts any
+ * other command
+ */
+ if (conn->needSync)
+ {
+ pgxc_node_send_sync(conn);
+ pgxc_node_receive(1, &conn, NULL);
+ }
/*
* Do not matter, is there committed or failed transaction,
* just send down rollback to finish it.
if (conn->transaction_status != 'I')
{
+ /* Send SYNC if the remote session is expecting one */
+ if (conn->needSync)
+ {
+ pgxc_node_send_sync(conn);
+ pgxc_node_receive(1, &conn, NULL);
+ }
/*
* Do not matter, is there committed or failed transaction,
* just send down rollback to finish it.
memcpy(handle->outBuffer + handle->outEnd, data_row, len);
handle->outEnd += len;
handle->outBuffer[handle->outEnd++] = '\n';
+
+ handle->in_extended_query = false;
}
else
{
memcpy(handle->outBuffer + handle->outEnd, &nLen, 4);
handle->outEnd += 4;
+ handle->in_extended_query = false;
/* We need response right away, so send immediately */
if (pgxc_node_flush(handle) < 0)
return true;
pgxc_handle->inEnd = 0;
pgxc_handle->inCursor = 0;
pgxc_handle->outEnd = 0;
+ pgxc_handle->needSync = false;
if (pgxc_handle->outBuffer == NULL || pgxc_handle->inBuffer == NULL)
{
handle->inStart = 0;
handle->inEnd = 0;
handle->inCursor = 0;
+ handle->needSync = false;
/*
* We got a new connection, set on the remote node the session parameters
* if defined. The transaction parameter should be sent after BEGIN
}
pfree(paramTypes);
+ handle->in_extended_query = true;
return 0;
}
handle->outBuffer[handle->outEnd++] = 0;
handle->outBuffer[handle->outEnd++] = 0;
+ handle->in_extended_query = true;
return 0;
}
else
handle->outBuffer[handle->outEnd++] = '\0';
+ handle->in_extended_query = true;
return 0;
}
else
handle->outBuffer[handle->outEnd++] = '\0';
+ handle->in_extended_query = true;
return 0;
}
PGXCNodeSetConnectionState(handle, DN_CONNECTION_STATE_QUERY);
+ handle->in_extended_query = true;
return 0;
}
memcpy(handle->outBuffer + handle->outEnd, &msgLen, 4);
handle->outEnd += 4;
+ handle->in_extended_query = true;
return pgxc_node_flush(handle);
}
memcpy(handle->outBuffer + handle->outEnd, &msgLen, 4);
handle->outEnd += 4;
+ handle->in_extended_query = false;
+ handle->needSync = false;
+
return pgxc_node_flush(handle);
}
PGXCNodeSetConnectionState(handle, DN_CONNECTION_STATE_QUERY);
+ handle->in_extended_query = false;
return pgxc_node_flush(handle);
}