Stop using PQsendQuery in libpq_pipeline
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 23 Sep 2022 16:11:48 +0000 (18:11 +0200)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 23 Sep 2022 16:11:48 +0000 (18:11 +0200)
The "emulation" I wrote for PQsendQuery in pipeline mode to use extended
query protocol, in commit acb7e4eb6b1c, is problematic.  Due to numerous
bugs we'll soon remove it.  As a first step and for all branches back to
14, stop using PQsendQuery in libpq_pipeline.  Also remove a few test
lines that will no longer be relevant.

Backpatch to 14.

Discussion: https://postgr.es/m/CA+mi_8ZGSQNmW6-mk_iSR4JZB_LJ4ww3suOF+1vGNs3MrLsv4g@mail.gmail.com

src/test/modules/libpq_pipeline/libpq_pipeline.c
src/test/modules/libpq_pipeline/traces/pipeline_abort.trace
src/test/modules/libpq_pipeline/traces/pipeline_idle.trace

index 6600ebb0c29f35677461d0410fae7ea1defdbe60..de4d75cfa82a129a00973e1cdb3926d172bf84d8 100644 (file)
@@ -497,7 +497,7 @@ test_pipeline_abort(PGconn *conn)
                                 PQerrorMessage(conn));
 
        /* Try to send two queries in one command */
-       if (PQsendQuery(conn, "SELECT 1; SELECT 2") != 1)
+       if (PQsendQueryParams(conn, "SELECT 1; SELECT 2", 0, NULL, NULL, NULL, NULL, 0) != 1)
                pg_fatal("failed to send query: %s", PQerrorMessage(conn));
        if (PQpipelineSync(conn) != 1)
                pg_fatal("pipeline sync failed: %s", PQerrorMessage(conn));
@@ -529,7 +529,8 @@ test_pipeline_abort(PGconn *conn)
        fprintf(stderr, "ok\n");
 
        /* Test single-row mode with an error partways */
-       if (PQsendQuery(conn, "SELECT 1.0/g FROM generate_series(3, -1, -1) g") != 1)
+       if (PQsendQueryParams(conn, "SELECT 1.0/g FROM generate_series(3, -1, -1) g",
+                                                 0, NULL, NULL, NULL, NULL, 0) != 1)
                pg_fatal("failed to send query: %s", PQerrorMessage(conn));
        if (PQpipelineSync(conn) != 1)
                pg_fatal("pipeline sync failed: %s", PQerrorMessage(conn));
@@ -989,133 +990,10 @@ test_pipeline_idle(PGconn *conn)
 
        PQsetNoticeProcessor(conn, notice_processor, &n_notices);
 
-       /*
-        * Cause a Close message to be sent to the server, and watch libpq's
-        * reaction to the resulting CloseComplete.  libpq must not get in IDLE
-        * state until that has been received.
-        */
-       if (PQenterPipelineMode(conn) != 1)
-               pg_fatal("failed to enter pipeline mode: %s", PQerrorMessage(conn));
-
-       if (PQsendQuery(conn, "SELECT 1") != 1)
-               pg_fatal("failed to send query: %s", PQerrorMessage(conn));
-       PQsendFlushRequest(conn);
-       res = PQgetResult(conn);
-       if (res == NULL)
-               pg_fatal("PQgetResult returned null when there's a pipeline item: %s",
-                                PQerrorMessage(conn));
-       if (PQresultStatus(res) != PGRES_TUPLES_OK)
-               pg_fatal("Unexpected result code %s from first pipeline item",
-                                PQresStatus(PQresultStatus(res)));
-       PQclear(res);
-
-       res = PQgetResult(conn);
-       if (res != NULL)
-               pg_fatal("expected NULL result");
-
-       if (PQpipelineSync(conn) != 1)
-               pg_fatal("pipeline sync failed: %s", PQerrorMessage(conn));
-       res = PQgetResult(conn);
-       if (res == NULL)
-               pg_fatal("PQgetResult returned null when there's a pipeline item: %s",
-                                PQerrorMessage(conn));
-       if (PQresultStatus(res) != PGRES_PIPELINE_SYNC)
-               pg_fatal("Unexpected result code %s instead of PGRES_PIPELINE_SYNC, error: %s",
-                                PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
-       PQclear(res);
-       res = NULL;
-
-       if (PQexitPipelineMode(conn) != 1)
-               pg_fatal("attempt to exit pipeline mode failed when it should've succeeded: %s",
-                                PQerrorMessage(conn));
-
-       /*
-        * Must not have got any notices here; note bug as described in
-        * https://postgr.es/m/CA+mi_8bvD0_CW3sumgwPvWdNzXY32itoG_16tDYRu_1S2gV2iw@mail.gmail.com
-        */
-       if (n_notices > 0)
-               pg_fatal("got %d notice(s)", n_notices);
-       fprintf(stderr, "ok - 1\n");
-
-       /*
-        * Verify that we can send a query using simple query protocol after one
-        * in pipeline mode.
-        */
-       if (PQenterPipelineMode(conn) != 1)
-               pg_fatal("failed to enter pipeline mode: %s", PQerrorMessage(conn));
-       if (PQsendQuery(conn, "SELECT 1") != 1)
-               pg_fatal("failed to send query: %s", PQerrorMessage(conn));
-       PQsendFlushRequest(conn);
-       res = PQgetResult(conn);
-       if (res == NULL)
-               pg_fatal("PQgetResult returned null when there's a pipeline item: %s",
-                                PQerrorMessage(conn));
-       if (PQresultStatus(res) != PGRES_TUPLES_OK)
-               pg_fatal("unexpected result code %s from first pipeline item",
-                                PQresStatus(PQresultStatus(res)));
-       res = PQgetResult(conn);
-       if (res != NULL)
-               pg_fatal("got unexpected non-null result");
-       /* We can exit pipeline mode now */
-       if (PQexitPipelineMode(conn) != 1)
-               pg_fatal("attempt to exit pipeline mode failed when it should've succeeded: %s",
-                                PQerrorMessage(conn));
-       res = PQexec(conn, "SELECT 2");
-       if (n_notices > 0)
-               pg_fatal("got %d notice(s)", n_notices);
-       if (res == NULL)
-               pg_fatal("PQexec returned NULL");
-       if (PQresultStatus(res) != PGRES_TUPLES_OK)
-               pg_fatal("unexpected result code %s from non-pipeline query",
-                                PQresStatus(PQresultStatus(res)));
-       res = PQgetResult(conn);
-       if (res != NULL)
-               pg_fatal("did not receive terminating NULL");
-       if (n_notices > 0)
-               pg_fatal("got %d notice(s)", n_notices);
-       fprintf(stderr, "ok - 2\n");
-
-       /*
-        * Case 2: exiting pipeline mode is not OK if a second command is sent.
-        */
-
-       if (PQenterPipelineMode(conn) != 1)
-               pg_fatal("failed to enter pipeline mode: %s", PQerrorMessage(conn));
-       if (PQsendQuery(conn, "SELECT 1") != 1)
-               pg_fatal("failed to send query: %s", PQerrorMessage(conn));
-       PQsendFlushRequest(conn);
-       res = PQgetResult(conn);
-       if (res == NULL)
-               pg_fatal("PQgetResult returned null when there's a pipeline item: %s",
-                                PQerrorMessage(conn));
-       if (PQresultStatus(res) != PGRES_TUPLES_OK)
-               pg_fatal("unexpected result code %s from first pipeline item",
-                                PQresStatus(PQresultStatus(res)));
-       if (PQsendQuery(conn, "SELECT 2") != 1)
-               pg_fatal("failed to send query: %s", PQerrorMessage(conn));
-       PQsendFlushRequest(conn);
-       /* read terminating null from first query */
-       res = PQgetResult(conn);
-       if (res != NULL)
-               pg_fatal("did not receive terminating NULL");
-       res = PQgetResult(conn);
-       if (res == NULL)
-               pg_fatal("PQgetResult returned null when there's a pipeline item: %s",
-                                PQerrorMessage(conn));
-       if (PQresultStatus(res) != PGRES_TUPLES_OK)
-               pg_fatal("unexpected result code %s from first pipeline item",
-                                PQresStatus(PQresultStatus(res)));
-       res = PQgetResult(conn);
-       if (res != NULL)
-               pg_fatal("did not receive terminating NULL");
-       if (PQexitPipelineMode(conn) != 1)
-               pg_fatal("attempt to exit pipeline mode failed when it should've succeeded: %s",
-                                PQerrorMessage(conn));
-
        /* Try to exit pipeline mode in pipeline-idle state */
        if (PQenterPipelineMode(conn) != 1)
                pg_fatal("failed to enter pipeline mode: %s", PQerrorMessage(conn));
-       if (PQsendQuery(conn, "SELECT 1") != 1)
+       if (PQsendQueryParams(conn, "SELECT 1", 0, NULL, NULL, NULL, NULL, 0) != 1)
                pg_fatal("failed to send query: %s", PQerrorMessage(conn));
        PQsendFlushRequest(conn);
        res = PQgetResult(conn);
@@ -1129,7 +1007,7 @@ test_pipeline_idle(PGconn *conn)
        res = PQgetResult(conn);
        if (res != NULL)
                pg_fatal("did not receive terminating NULL");
-       if (PQsendQuery(conn, "SELECT 2") != 1)
+       if (PQsendQueryParams(conn, "SELECT 2", 0, NULL, NULL, NULL, NULL, 0) != 1)
                pg_fatal("failed to send query: %s", PQerrorMessage(conn));
        if (PQexitPipelineMode(conn) == 1)
                pg_fatal("exiting pipeline succeeded when it shouldn't");
@@ -1151,12 +1029,12 @@ test_pipeline_idle(PGconn *conn)
 
        if (n_notices > 0)
                pg_fatal("got %d notice(s)", n_notices);
-       fprintf(stderr, "ok - 3\n");
+       fprintf(stderr, "ok - 1\n");
 
        /* Have a WARNING in the middle of a resultset */
        if (PQenterPipelineMode(conn) != 1)
                pg_fatal("entering pipeline mode failed: %s", PQerrorMessage(conn));
-       if (PQsendQuery(conn, "SELECT pg_catalog.pg_advisory_unlock(1,1)") != 1)
+       if (PQsendQueryParams(conn, "SELECT pg_catalog.pg_advisory_unlock(1,1)", 0, NULL, NULL, NULL, NULL, 0) != 1)
                pg_fatal("failed to send query: %s", PQerrorMessage(conn));
        PQsendFlushRequest(conn);
        res = PQgetResult(conn);
@@ -1166,7 +1044,7 @@ test_pipeline_idle(PGconn *conn)
                pg_fatal("unexpected result code %s", PQresStatus(PQresultStatus(res)));
        if (PQexitPipelineMode(conn) != 1)
                pg_fatal("failed to exit pipeline mode: %s", PQerrorMessage(conn));
-       fprintf(stderr, "ok - 4\n");
+       fprintf(stderr, "ok - 2\n");
 }
 
 static void
index 3fce548b99547713aca6478b9f54b6ab55cac2fc..cf6ccec6b9d190f01f353327d9f42f8ff4dca5f0 100644 (file)
@@ -35,18 +35,16 @@ B   4       NoData
 B      15      CommandComplete  "INSERT 0 1"
 B      5       ReadyForQuery    I
 F      26      Parse    "" "SELECT 1; SELECT 2" 0
-F      12      Bind     "" "" 0 0 0
+F      14      Bind     "" "" 0 0 1 0
 F      6       Describe         P ""
 F      9       Execute  "" 0
-F      6       Close    P ""
 F      4       Sync
 B      NN      ErrorResponse    S "ERROR" V "ERROR" C "42601" M "cannot insert multiple commands into a prepared statement" F "SSSS" L "SSSS" R "SSSS" \x00
 B      5       ReadyForQuery    I
 F      54      Parse    "" "SELECT 1.0/g FROM generate_series(3, -1, -1) g" 0
-F      12      Bind     "" "" 0 0 0
+F      14      Bind     "" "" 0 0 1 0
 F      6       Describe         P ""
 F      9       Execute  "" 0
-F      6       Close    P ""
 F      4       Sync
 B      4       ParseComplete
 B      4       BindComplete
index 3957ee4dfe156d15e461c8669945137ada5e9e5d..83ee415b03e4d98023344957a099bab4df95d036 100644 (file)
@@ -1,87 +1,27 @@
 F      16      Parse    "" "SELECT 1" 0
-F      12      Bind     "" "" 0 0 0
+F      14      Bind     "" "" 0 0 1 0
 F      6       Describe         P ""
 F      9       Execute  "" 0
-F      6       Close    P ""
 F      4       Flush
 B      4       ParseComplete
 B      4       BindComplete
 B      33      RowDescription   1 "?column?" NNNN 0 NNNN 4 -1 0
 B      11      DataRow  1 1 '1'
 B      13      CommandComplete  "SELECT 1"
-B      4       CloseComplete
-F      4       Sync
-B      5       ReadyForQuery    I
-F      16      Parse    "" "SELECT 1" 0
-F      12      Bind     "" "" 0 0 0
-F      6       Describe         P ""
-F      9       Execute  "" 0
-F      6       Close    P ""
-F      4       Flush
-B      4       ParseComplete
-B      4       BindComplete
-B      33      RowDescription   1 "?column?" NNNN 0 NNNN 4 -1 0
-B      11      DataRow  1 1 '1'
-B      13      CommandComplete  "SELECT 1"
-B      4       CloseComplete
-F      13      Query    "SELECT 2"
-B      33      RowDescription   1 "?column?" NNNN 0 NNNN 4 -1 0
-B      11      DataRow  1 1 '2'
-B      13      CommandComplete  "SELECT 1"
-B      5       ReadyForQuery    I
-F      16      Parse    "" "SELECT 1" 0
-F      12      Bind     "" "" 0 0 0
-F      6       Describe         P ""
-F      9       Execute  "" 0
-F      6       Close    P ""
-F      4       Flush
-B      4       ParseComplete
-B      4       BindComplete
-B      33      RowDescription   1 "?column?" NNNN 0 NNNN 4 -1 0
-B      11      DataRow  1 1 '1'
-B      13      CommandComplete  "SELECT 1"
-B      4       CloseComplete
-F      16      Parse    "" "SELECT 2" 0
-F      12      Bind     "" "" 0 0 0
-F      6       Describe         P ""
-F      9       Execute  "" 0
-F      6       Close    P ""
-F      4       Flush
-B      4       ParseComplete
-B      4       BindComplete
-B      33      RowDescription   1 "?column?" NNNN 0 NNNN 4 -1 0
-B      11      DataRow  1 1 '2'
-B      13      CommandComplete  "SELECT 1"
-B      4       CloseComplete
-F      16      Parse    "" "SELECT 1" 0
-F      12      Bind     "" "" 0 0 0
-F      6       Describe         P ""
-F      9       Execute  "" 0
-F      6       Close    P ""
-F      4       Flush
-B      4       ParseComplete
-B      4       BindComplete
-B      33      RowDescription   1 "?column?" NNNN 0 NNNN 4 -1 0
-B      11      DataRow  1 1 '1'
-B      13      CommandComplete  "SELECT 1"
-B      4       CloseComplete
 F      16      Parse    "" "SELECT 2" 0
-F      12      Bind     "" "" 0 0 0
+F      14      Bind     "" "" 0 0 1 0
 F      6       Describe         P ""
 F      9       Execute  "" 0
-F      6       Close    P ""
 F      4       Flush
 B      4       ParseComplete
 B      4       BindComplete
 B      33      RowDescription   1 "?column?" NNNN 0 NNNN 4 -1 0
 B      11      DataRow  1 1 '2'
 B      13      CommandComplete  "SELECT 1"
-B      4       CloseComplete
 F      49      Parse    "" "SELECT pg_catalog.pg_advisory_unlock(1,1)" 0
-F      12      Bind     "" "" 0 0 0
+F      14      Bind     "" "" 0 0 1 0
 F      6       Describe         P ""
 F      9       Execute  "" 0
-F      6       Close    P ""
 F      4       Flush
 B      4       ParseComplete
 B      4       BindComplete
@@ -89,5 +29,4 @@ B     43      RowDescription   1 "pg_advisory_unlock" NNNN 0 NNNN 1 -1 0
 B      NN      NoticeResponse   S "WARNING" V "WARNING" C "01000" M "you don't own a lock of type ExclusiveLock" F "SSSS" L "SSSS" R "SSSS" \x00
 B      11      DataRow  1 1 'f'
 B      13      CommandComplete  "SELECT 1"
-B      4       CloseComplete
 F      4       Terminate