At Tue, 21 Jun 2022 11:42:59 +0900 (JST), Kyotaro Horiguchi <horikyota....@gmail.com> wrote in > At Fri, 17 Jun 2022 20:31:50 +0200, Alvaro Herrera <alvhe...@alvh.no-ip.org> > wrote in > > Others to think about: > > > > PQisBusy (I think no changes are needed), > > Agreed. > > > PQfn (I think it should accept a call in PGASYNC_PIPELINE_IDLE mode; > > fully untested in pipeline mode), > > Does a PQ_PIPELINE_OFF path need that? Rather I thought that we need > Assert(!conn->asyncStatus != PGASYNC_PIPELINE_IDLE) there. But anyway > we might need a test for this path.
In the attached, PQfn() is used while in pipeline mode and PGASYNC_PIPELINE_IDLE. Both error out and effectivelly no-op. > > PQexitPipelineMode (I think it needs to return error; needs test case), > > Agreed about test case. Currently the function doesn't handle > PGASYNC_IDLE so I thought that PGASYNC_PIPELINE_IDLE also don't need a > care. If the function treats PGASYNC_PIPELINE_IDLE state as error, > the regression test fails (but I haven't examine it furtuer.) PQexitPipelineMode() is called while PGASYNC_PIPELINE_IDLE. > > PQsendFlushRequest (I think it should let through; ditto). > > Does that mean exit without pushing 'H' message? I didn't do anything on this in the sttached. By the way, I noticed that "libpq_pipeline uniqviol" intermittently fails for uncertain reasons. > result 574/575: pipeline aborted > ........................................................... > done writing > > libpq_pipeline:1531: got unexpected NULL The "...........done writing" is printed too late in the error cases. This causes the TAP test fail, but I haven't find what's happnening at the time. regards. -- Kyotaro Horiguchi NTT Open Source Software Center
diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c index 0ff563f59a..84734f5d41 100644 --- a/src/test/modules/libpq_pipeline/libpq_pipeline.c +++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c @@ -53,6 +53,8 @@ static const char *const insert_sql = static const char *const insert_sql2 = "INSERT INTO pq_pipeline_demo(itemno,int8filler) VALUES ($1, $2)"; +Oid oid_pg_backend_pid; + /* max char length of an int32/64, plus sign and null terminator */ #define MAXINTLEN 12 #define MAXINT8LEN 20 @@ -86,6 +88,24 @@ pg_fatal_impl(int line, const char *fmt,...) exit(1); } +/* returns true if PQfn succeeded */ +static bool +PQfn_succeed(PGconn *conn) +{ + PGresult *res; + int res_buf; + int res_len; + + /* PQfn should fail in pipeline mode */ + if ((res = PQfn(conn, oid_pg_backend_pid, &res_buf, &res_len, 1, NULL, 0)) + != NULL && + PQresultStatus(res) == PGRES_COMMAND_OK) + return true; + + return false; +} + + static void test_disallowed_in_pipeline(PGconn *conn) { @@ -93,6 +113,9 @@ test_disallowed_in_pipeline(PGconn *conn) fprintf(stderr, "test error cases... "); + if (oid_pg_backend_pid == 0) + pg_fatal("Failed to obtain functino oid: %s", PQgetvalue(res, 0, 0)); + if (PQisnonblocking(conn)) pg_fatal("Expected blocking connection mode"); @@ -107,6 +130,10 @@ test_disallowed_in_pipeline(PGconn *conn) if (PQresultStatus(res) != PGRES_FATAL_ERROR) pg_fatal("PQexec should fail in pipeline mode but succeeded"); + /* PQfn should fail in pipeline mode */ + if (PQfn_succeed(conn)) + pg_fatal("PQfn succeeded while in pipeline mode"); + /* Entering pipeline mode when already in pipeline mode is OK */ if (PQenterPipelineMode(conn) != 1) pg_fatal("re-entering pipeline mode should be a no-op but failed"); @@ -1014,6 +1041,18 @@ test_simple_pipeline(PGconn *conn) PQclear(res); res = NULL; + /* PQfn shoud be error no-op while PGASYNC_PIPELINE_IDLE */ + if (PQfn_succeed(conn)) + pg_fatal("PQfn succeeded while in pipeline mode"); + + /* + * Trial to getting out of pipeline mode while PGASYNC_PIPELINE_IDLE should + * gracefully fail. + */ + if (PQexitPipelineMode(conn) != 0) + pg_fatal("exiting pipeline mode after query but before sync succeeded incorrectly"); + + /* This PQgetResult moves async status to PGASYNC_BUSY */ if (PQgetResult(conn) != NULL) pg_fatal("PQgetResult returned something extra after first query result."); @@ -1627,6 +1666,15 @@ main(int argc, char **argv) if (PQresultStatus(res) != PGRES_COMMAND_OK) pg_fatal("failed to set force_parallel_mode: %s", PQerrorMessage(conn)); + /* obtain function OID of pg_backend_pid for PQfn test */ + res = PQexec(conn, "SELECT 'pg_backend_pid'::regproc::int"); + if (!res || + (PQresultStatus(res) != PGRES_COMMAND_OK && + PQresultStatus(res) != PGRES_TUPLES_OK)) + pg_fatal("Failed to obtain functino oid"); + + oid_pg_backend_pid = atoi(PQgetvalue(res, 0, 0)); + /* Set the trace file, if requested */ if (tracefile != NULL) {