aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-exec.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2022-09-23 18:21:22 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2022-09-23 18:21:22 +0200
commitbd8ac900df4d2824f50ce4b1674754685aeaed56 (patch)
treebd294efdef49f4a3dd022bfec6ef8bd7aa9a6280 /src/interfaces/libpq/fe-exec.c
parent27e04412c9c3c3c3b2d182821c759f95693c0039 (diff)
downloadpostgresql-bd8ac900df4d2824f50ce4b1674754685aeaed56.tar.gz
postgresql-bd8ac900df4d2824f50ce4b1674754685aeaed56.zip
Remove PQsendQuery support in pipeline mode
The extended query protocol implementation I added in commit acb7e4eb6b1c has bugs when used in pipeline mode. Rather than spend more time trying to fix it, remove that code and make the function rely on simple query protocol only, meaning it can no longer be used in pipeline mode. Users can easily change their applications to use PQsendQueryParams instead. We leave PQsendQuery in place for Postgres 14, just in case somebody is using it and has not hit the mentioned bugs; but we should recommend that it not be used. Backpatch to 15. Per bug report from Gabriele Varrazzo. Discussion: https://postgr.es/m/CA+mi_8ZGSQNmW6-mk_iSR4JZB_LJ4ww3suOF+1vGNs3MrLsv4g@mail.gmail.com
Diffstat (limited to 'src/interfaces/libpq/fe-exec.c')
-rw-r--r--src/interfaces/libpq/fe-exec.c117
1 files changed, 23 insertions, 94 deletions
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index 23ceff75024..8484c4dda1a 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -1437,7 +1437,6 @@ static int
PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
{
PGcmdQueueEntry *entry = NULL;
- PGcmdQueueEntry *entry2 = NULL;
if (!PQsendQueryStart(conn, newQuery))
return 0;
@@ -1450,103 +1449,48 @@ PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
return 0;
}
- entry = pqAllocCmdQueueEntry(conn);
- if (entry == NULL)
- return 0; /* error msg already set */
if (conn->pipelineStatus != PQ_PIPELINE_OFF)
{
- entry2 = pqAllocCmdQueueEntry(conn);
- if (entry2 == NULL)
- goto sendFailed;
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("%s not allowed in pipeline mode\n"),
+ "PQsendQuery");
+ return 0;
}
+ entry = pqAllocCmdQueueEntry(conn);
+ if (entry == NULL)
+ return 0; /* error msg already set */
+
/* Send the query message(s) */
- if (conn->pipelineStatus == PQ_PIPELINE_OFF)
+ /* construct the outgoing Query message */
+ if (pqPutMsgStart('Q', conn) < 0 ||
+ pqPuts(query, conn) < 0 ||
+ pqPutMsgEnd(conn) < 0)
{
- /* construct the outgoing Query message */
- if (pqPutMsgStart('Q', conn) < 0 ||
- pqPuts(query, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- {
- /* error message should be set up already */
- pqRecycleCmdQueueEntry(conn, entry);
- return 0;
- }
-
- /* remember we are using simple query protocol */
- entry->queryclass = PGQUERY_SIMPLE;
- /* and remember the query text too, if possible */
- entry->query = strdup(query);
+ /* error message should be set up already */
+ pqRecycleCmdQueueEntry(conn, entry);
+ return 0;
}
- else
- {
- /*
- * In pipeline mode we cannot use the simple protocol, so we send
- * Parse, Bind, Describe Portal, Execute, Close Portal (with the
- * unnamed portal).
- */
- if (pqPutMsgStart('P', conn) < 0 ||
- pqPuts("", conn) < 0 ||
- pqPuts(query, conn) < 0 ||
- pqPutInt(0, 2, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
- if (pqPutMsgStart('B', conn) < 0 ||
- pqPuts("", conn) < 0 ||
- pqPuts("", conn) < 0 ||
- pqPutInt(0, 2, conn) < 0 ||
- pqPutInt(0, 2, conn) < 0 ||
- pqPutInt(0, 2, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
- if (pqPutMsgStart('D', conn) < 0 ||
- pqPutc('P', conn) < 0 ||
- pqPuts("", conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
- if (pqPutMsgStart('E', conn) < 0 ||
- pqPuts("", conn) < 0 ||
- pqPutInt(0, 4, conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
- if (pqPutMsgStart('C', conn) < 0 ||
- pqPutc('P', conn) < 0 ||
- pqPuts("", conn) < 0 ||
- pqPutMsgEnd(conn) < 0)
- goto sendFailed;
- entry->queryclass = PGQUERY_EXTENDED;
- entry->query = strdup(query);
- }
+ /* remember we are using simple query protocol */
+ entry->queryclass = PGQUERY_SIMPLE;
+ /* and remember the query text too, if possible */
+ entry->query = strdup(query);
/*
* Give the data a push. In nonblock mode, don't complain if we're unable
* to send it all; PQgetResult() will do any additional flushing needed.
*/
- if (pqPipelineFlush(conn) < 0)
+ if (pqFlush(conn) < 0)
goto sendFailed;
/* OK, it's launched! */
pqAppendCmdQueueEntry(conn, entry);
- /*
- * When pipeline mode is in use, we need a second entry in the command
- * queue to represent Close Portal message. This allows us later to wait
- * for the CloseComplete message to be received before getting in IDLE
- * state.
- */
- if (conn->pipelineStatus != PQ_PIPELINE_OFF)
- {
- entry2->queryclass = PGQUERY_CLOSE;
- entry2->query = NULL;
- pqAppendCmdQueueEntry(conn, entry2);
- }
-
return 1;
sendFailed:
pqRecycleCmdQueueEntry(conn, entry);
- pqRecycleCmdQueueEntry(conn, entry2);
/* error message should be set up already */
return 0;
}
@@ -2250,22 +2194,6 @@ PQgetResult(PGconn *conn)
break;
}
- /* If the next command we expect is CLOSE, read and consume it */
- if (conn->asyncStatus == PGASYNC_PIPELINE_IDLE &&
- conn->cmd_queue_head &&
- conn->cmd_queue_head->queryclass == PGQUERY_CLOSE)
- {
- if (res && res->resultStatus != PGRES_FATAL_ERROR)
- {
- conn->asyncStatus = PGASYNC_BUSY;
- parseInput(conn);
- conn->asyncStatus = PGASYNC_PIPELINE_IDLE;
- }
- else
- /* we won't ever see the Close */
- pqCommandQueueAdvance(conn);
- }
-
/* Time to fire PGEVT_RESULTCREATE events, if there are any */
if (res && res->nEvents > 0)
(void) PQfireResultCreateEvents(conn, res);
@@ -2982,8 +2910,9 @@ PQfn(PGconn *conn,
if (conn->pipelineStatus != PQ_PIPELINE_OFF)
{
- appendPQExpBufferStr(&conn->errorMessage,
- libpq_gettext("PQfn not allowed in pipeline mode\n"));
+ appendPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("%s not allowed in pipeline mode\n"),
+ "PQfn");
return NULL;
}