v5-0009-Add-tests-for-ParameterSet-and-_pq_.protocol_mana.patch
application/octet-stream
Filename: v5-0009-Add-tests-for-ParameterSet-and-_pq_.protocol_mana.patch
Type: application/octet-stream
Part: 6
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v5-0009
Subject: Add tests for ParameterSet and _pq_.protocol_managed_params
| File | + | − |
|---|---|---|
| src/test/modules/libpq_pipeline/libpq_pipeline.c | 410 | 0 |
| src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl | 1 | 1 |
| src/test/modules/libpq_pipeline/traces/parameter_set.trace | 182 | 0 |
From 71d3c26545538e62f089a619a9f6dc1d020d126d Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <jelte.fennema@microsoft.com>
Date: Sun, 7 Jan 2024 11:24:10 +0100
Subject: [PATCH v5 9/9] Add tests for ParameterSet and
_pq_.protocol_managed_params
---
.../modules/libpq_pipeline/libpq_pipeline.c | 410 ++++++++++++++++++
.../libpq_pipeline/t/001_libpq_pipeline.pl | 2 +-
.../libpq_pipeline/traces/parameter_set.trace | 182 ++++++++
3 files changed, 593 insertions(+), 1 deletion(-)
create mode 100644 src/test/modules/libpq_pipeline/traces/parameter_set.trace
diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c
index 71cd04c5f23..b93156b62db 100644
--- a/src/test/modules/libpq_pipeline/libpq_pipeline.c
+++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c
@@ -1046,6 +1046,413 @@ test_prepared(PGconn *conn)
fprintf(stderr, "ok\n");
}
+static void
+test_parameter_set(PGconn *conn)
+{
+ PGresult *res = NULL;
+ const char *val;
+
+ res = PQparameterSet(conn, "work_mem", "123MB");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to set parameter: %s", PQerrorMessage(conn));
+
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "123MB") != 0)
+ pg_fatal("expected 123MB, got %s", val);
+ PQclear(res);
+
+
+ /* Outside of a pipeline */
+ res = PQexec(conn, "SHOW _pq_.protocol_managed_params");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "") != 0)
+ pg_fatal("expected work_mem, got %s", val);
+
+ if (PQsendParameterSet(conn, "_pq_.protocol_managed_params", "work_mem") != 1)
+ pg_fatal("PQsendParameterSet failed: %s", PQerrorMessage(conn));
+ res = PQgetResult(conn);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to set parameter: %s", PQerrorMessage(conn));
+ PQclear(res);
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+
+ res = PQexec(conn, "SHOW _pq_.protocol_managed_params");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "work_mem") != 0)
+ pg_fatal("expected work_mem, got %s", val);
+
+ if (PQsendParameterSet(conn, "work_mem", "42MB") != 1)
+ pg_fatal("PQsendParameterSet failed: %s", PQerrorMessage(conn));
+ res = PQgetResult(conn);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to set parameter: %s", PQerrorMessage(conn));
+ PQclear(res);
+
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "42MB") != 0)
+ pg_fatal("expected 42MB, got %s", val);
+ PQclear(res);
+
+ res = PQexec(conn, "RESET ALL");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+
+ res = PQexec(conn, "SHOW _pq_.protocol_managed_params");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "work_mem") != 0)
+ pg_fatal("expected 42MB, got %s", val);
+
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "42MB") != 0)
+ pg_fatal("expected 42MB, got %s", val);
+ PQclear(res);
+
+ /* In a pipeline with other queries */
+ if (PQenterPipelineMode(conn) != 1)
+ pg_fatal("failed to enter pipeline mode: %s", PQerrorMessage(conn));
+ if (PQsendParameterSet(conn, "work_mem", "10MB") != 1)
+ pg_fatal("PQsendParameterSet failed: %s", PQerrorMessage(conn));
+ PQsendFlushRequest(conn);
+ res = PQgetResult(conn);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to set parameter: %s", PQerrorMessage(conn));
+ PQclear(res);
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+
+ /*
+ * This is fine, but it opens an implicit transaction which should cause
+ * the next ParameterSet message to fail
+ */
+ if (PQsendQueryParams(conn, "SHOW work_mem", 0, NULL, NULL, NULL, NULL, 0) != 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)));
+
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "10MB") != 0)
+ pg_fatal("expected 10MB, got %s", val);
+
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+
+ if (PQsendParameterSet(conn, "work_mem", "12MB") != 1)
+ pg_fatal("PQsendParameterSet failed: %s", PQerrorMessage(conn));
+ PQsendFlushRequest(conn);
+ res = PQgetResult(conn);
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("Should not be allowed to set work_mem anymore using ParameterSet in an implicit transaction");
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+
+ if (PQpipelineSync(conn) != 1)
+ pg_fatal("pipeline sync failed: %s", PQerrorMessage(conn));
+ res = PQgetResult(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));
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+ if (PQexitPipelineMode(conn) != 1)
+ pg_fatal("exiting pipeline failed: %s", PQerrorMessage(conn));
+
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "10MB") != 0)
+ pg_fatal("expected 10MB, got %s", val);
+ PQclear(res);
+
+ /* In transaction */
+ res = PQexec(conn, "BEGIN");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to begin transaction: %s", PQerrorMessage(conn));
+
+ res = PQparameterSet(conn, "work_mem", "30MB");
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("Should not be allowed to set work_mem anymore using ParameterSet in an explicit transaction");
+
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("transaction should have been aborted");
+
+ res = PQexec(conn, "ROLLBACK");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to set parameter: %s", PQerrorMessage(conn));
+
+ /* it behaves transactionally */
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "10MB") != 0)
+ pg_fatal("expected 10MB, got %s", val);
+ PQclear(res);
+
+ /* In a failed pipeline */
+ if (PQenterPipelineMode(conn) != 1)
+ pg_fatal("failed to enter pipeline mode: %s", PQerrorMessage(conn));
+ if (PQsendQueryParams(conn, "SELECT 0/0", 0, NULL, NULL, NULL, NULL, 0) != 1)
+ pg_fatal("failed to send query: %s", PQerrorMessage(conn));
+ if (PQsendParameterSet(conn, "work_mem", "12MB") != 1)
+ pg_fatal("PQsendParameterSet failed: %s", PQerrorMessage(conn));
+ if (PQpipelineSync(conn) != 1)
+ pg_fatal("pipeline sync failed: %s", PQerrorMessage(conn));
+ res = PQgetResult(conn);
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("PQexec should have failed with division by zero");
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+ res = PQgetResult(conn);
+ if (PQresultStatus(res) != PGRES_PIPELINE_ABORTED)
+ pg_fatal("pipeline was not aborted");
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+ res = PQgetResult(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));
+ if (PQexitPipelineMode(conn) != 1)
+ pg_fatal("exiting pipeline failed: %s", PQerrorMessage(conn));
+
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "10MB") != 0)
+ pg_fatal("expected 10MB, got %s", val);
+ PQclear(res);
+
+ res = PQparameterSet(conn, "_pq_.protocol_managed_params", "role,session_authorization");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to set parameter: %s", PQerrorMessage(conn));
+
+ res = PQparameterSet(conn, "work_mem", "19MB");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to set parameter: %s", PQerrorMessage(conn));
+
+ /*
+ * Now ParemeterSet for work_mem should be allowed again in transaction and
+ * it should behave transactionally. First we show an implicit transaction
+ * that commits.
+ */
+ if (PQenterPipelineMode(conn) != 1)
+ pg_fatal("failed to enter pipeline mode: %s", PQerrorMessage(conn));
+ if (PQsendQueryParams(conn, "SHOW work_mem", 0, NULL, NULL, NULL, NULL, 0) != 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)));
+
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "19MB") != 0)
+ pg_fatal("expected 19MB, got %s", val);
+
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+
+ if (PQsendParameterSet(conn, "work_mem", "12MB") != 1)
+ pg_fatal("PQsendParameterSet failed: %s", PQerrorMessage(conn));
+ PQsendFlushRequest(conn);
+ res = PQgetResult(conn);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("Unexpected result code %s instead of PGRES_COMMAND_OK error: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+
+ if (PQpipelineSync(conn) != 1)
+ pg_fatal("pipeline sync failed: %s", PQerrorMessage(conn));
+ res = PQgetResult(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));
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+ if (PQexitPipelineMode(conn) != 1)
+ pg_fatal("exiting pipeline failed: %s", PQerrorMessage(conn));
+
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "12MB") != 0)
+ pg_fatal("expected 12MB, got %s", val);
+ PQclear(res);
+
+ /* Then we show an implicit transaction that rolls back ParameterSet */
+ if (PQenterPipelineMode(conn) != 1)
+ pg_fatal("failed to enter pipeline mode: %s", PQerrorMessage(conn));
+ if (PQsendParameterSet(conn, "work_mem", "28MB") != 1)
+ pg_fatal("PQsendParameterSet failed: %s", PQerrorMessage(conn));
+ if (PQsendQueryParams(conn, "SELECT 0/0", 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));
+ res = PQgetResult(conn);
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("Unexpected result code %s instead of PGRES_COMMAND_OK error: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+ res = PQgetResult(conn);
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("PQexec should have failed with division by zero");
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+
+ res = PQgetResult(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));
+ res = PQgetResult(conn);
+ if (res != NULL)
+ pg_fatal("did not receive terminating NULL");
+ if (PQexitPipelineMode(conn) != 1)
+ pg_fatal("exiting pipeline failed: %s", PQerrorMessage(conn));
+
+ /* check that it is rolled back */
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "12MB") != 0)
+ pg_fatal("expected 12MB, got %s", val);
+ PQclear(res);
+
+
+ /* Then we show an explicit transaction that rolls back ParameterSet */
+ res = PQexec(conn, "BEGIN");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to begin transaction: %s", PQerrorMessage(conn));
+
+ res = PQparameterSet(conn, "work_mem", "30MB");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to set parameter: %s", PQerrorMessage(conn));
+
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ if (PQntuples(res) != 1)
+ pg_fatal("expected 1 result, got %d", PQntuples(res));
+
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "30MB") != 0)
+ pg_fatal("expected 30MB, got %s", val);
+ PQclear(res);
+
+ res = PQexec(conn, "ROLLBACK");
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("failed to set parameter: %s", PQerrorMessage(conn));
+
+ /* it behaves transactionally */
+ res = PQexec(conn, "SHOW work_mem");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("Expected tuples, got %s: %s",
+ PQresStatus(PQresultStatus(res)), PQerrorMessage(conn));
+ val = PQgetvalue(res, 0, 0);
+ if (strcmp(val, "12MB") != 0)
+ pg_fatal("expected 12MB, got %s", val);
+ PQclear(res);
+
+
+ res = PQexec(conn, "SET SESSION AUTHORIZATION 'postgres'");
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("Should not be allowed to set SESSION AUTHORIZATION anymore using ParameterSet");
+
+ res = PQexec(conn, "SET ROLE 'postgres'");
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("Should not be allowed to set ROLE anymore using ParameterSet");
+ res = PQparameterSet(conn, "_pq_.protocol_managed_params", "doesnotexist");
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("Should not be allowed to use an unknown GUC");
+
+ res = PQparameterSet(conn, "_pq_.protocol_managed_params", "work_mem,_pq_.protocol_managed_params");
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("Should not be allowed to use a protocol extension");
+
+ res = PQparameterSet(conn, "_pq_.protocol_managed_params", "\"");
+ if (PQresultStatus(res) != PGRES_FATAL_ERROR)
+ pg_fatal("Should not be allowed to use invalid list syntax");
+}
+
/* Notice processor: print notices, and count how many we got */
static void
notice_processor(void *arg, const char *message)
@@ -1749,6 +2156,7 @@ print_test_list(void)
printf("disallowed_in_pipeline\n");
printf("multi_pipelines\n");
printf("nosync\n");
+ printf("parameter_set\n");
printf("pipeline_abort\n");
printf("pipeline_idle\n");
printf("pipelined_insert\n");
@@ -1853,6 +2261,8 @@ main(int argc, char **argv)
test_multi_pipelines(conn);
else if (strcmp(testname, "nosync") == 0)
test_nosync(conn);
+ else if (strcmp(testname, "parameter_set") == 0)
+ test_parameter_set(conn);
else if (strcmp(testname, "pipeline_abort") == 0)
test_pipeline_abort(conn);
else if (strcmp(testname, "pipeline_idle") == 0)
diff --git a/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl b/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl
index f9e6d07fc0b..eec5d954bf0 100644
--- a/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl
+++ b/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl
@@ -37,7 +37,7 @@ for my $testname (@tests)
{
my @extraargs = ('-r', $numrows);
my $cmptrace = grep(/^$testname$/,
- qw(simple_pipeline nosync multi_pipelines prepared singlerow
+ qw(simple_pipeline nosync multi_pipelines parameter_set prepared singlerow
pipeline_abort pipeline_idle transaction
disallowed_in_pipeline)) > 0;
diff --git a/src/test/modules/libpq_pipeline/traces/parameter_set.trace b/src/test/modules/libpq_pipeline/traces/parameter_set.trace
new file mode 100644
index 00000000000..66770252f18
--- /dev/null
+++ b/src/test/modules/libpq_pipeline/traces/parameter_set.trace
@@ -0,0 +1,182 @@
+F 19 ParameterSet "work_mem" "123MB"
+F 4 Sync
+B 4 ParameterSetComplete
+B 5 ReadyForQuery I
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 15 DataRow 1 5 '123MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 38 Query "SHOW _pq_.protocol_managed_params"
+B 53 RowDescription 1 "_pq_.protocol_managed_params" NNNN 0 NNNN 65535 -1 0
+B 10 DataRow 1 0 ''
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 42 ParameterSet "_pq_.protocol_managed_params" "work_mem"
+F 4 Sync
+B 4 ParameterSetComplete
+B 5 ReadyForQuery I
+F 38 Query "SHOW _pq_.protocol_managed_params"
+B 53 RowDescription 1 "_pq_.protocol_managed_params" NNNN 0 NNNN 65535 -1 0
+B 18 DataRow 1 8 'work_mem'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 18 ParameterSet "work_mem" "42MB"
+F 4 Sync
+B 4 ParameterSetComplete
+B 5 ReadyForQuery I
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '42MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 14 Query "RESET ALL"
+B 10 CommandComplete "RESET"
+B 5 ReadyForQuery I
+F 38 Query "SHOW _pq_.protocol_managed_params"
+B 53 RowDescription 1 "_pq_.protocol_managed_params" NNNN 0 NNNN 65535 -1 0
+B 18 DataRow 1 8 'work_mem'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '42MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 18 ParameterSet "work_mem" "10MB"
+F 4 Flush
+B 4 ParameterSetComplete
+F 21 Parse "" "SHOW work_mem" 0
+F 14 Bind "" "" 0 0 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 4 Flush
+B 4 ParseComplete
+B 4 BindComplete
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '10MB'
+B 9 CommandComplete "SHOW"
+F 18 ParameterSet "work_mem" "12MB"
+F 4 Flush
+B NN ErrorResponse S "ERROR" V "ERROR" C "25001" M "parameter "work_mem" cannot be changed within a transaction" F "SSSS" L "SSSS" R "SSSS" \x00
+F 4 Sync
+B 5 ReadyForQuery I
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '10MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 10 Query "BEGIN"
+B 10 CommandComplete "BEGIN"
+B 5 ReadyForQuery T
+F 18 ParameterSet "work_mem" "30MB"
+F 4 Sync
+B NN ErrorResponse S "ERROR" V "ERROR" C "25001" M "parameter "work_mem" cannot be changed within a transaction" F "SSSS" L "SSSS" R "SSSS" \x00
+B 5 ReadyForQuery E
+F 18 Query "SHOW work_mem"
+B NN ErrorResponse S "ERROR" V "ERROR" C "25P02" M "current transaction is aborted, commands ignored until end of transaction block" F "SSSS" L "SSSS" R "SSSS" \x00
+B 5 ReadyForQuery E
+F 13 Query "ROLLBACK"
+B 13 CommandComplete "ROLLBACK"
+B 5 ReadyForQuery I
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '10MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 18 Parse "" "SELECT 0/0" 0
+F 14 Bind "" "" 0 0 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 18 ParameterSet "work_mem" "12MB"
+F 4 Sync
+B 4 ParseComplete
+B NN ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
+B 5 ReadyForQuery I
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '10MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 60 ParameterSet "_pq_.protocol_managed_params" "role,session_authorization"
+F 4 Sync
+B 4 ParameterSetComplete
+B 5 ReadyForQuery I
+F 18 ParameterSet "work_mem" "19MB"
+F 4 Sync
+B 4 ParameterSetComplete
+B 5 ReadyForQuery I
+F 21 Parse "" "SHOW work_mem" 0
+F 14 Bind "" "" 0 0 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 4 Flush
+B 4 ParseComplete
+B 4 BindComplete
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '19MB'
+B 9 CommandComplete "SHOW"
+F 18 ParameterSet "work_mem" "12MB"
+F 4 Flush
+B 4 ParameterSetComplete
+F 4 Sync
+B 5 ReadyForQuery I
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '12MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 18 ParameterSet "work_mem" "28MB"
+F 18 Parse "" "SELECT 0/0" 0
+F 14 Bind "" "" 0 0 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 4 Sync
+B 4 ParameterSetComplete
+B 4 ParseComplete
+B NN ErrorResponse S "ERROR" V "ERROR" C "22012" M "division by zero" F "SSSS" L "SSSS" R "SSSS" \x00
+B 5 ReadyForQuery I
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '12MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 10 Query "BEGIN"
+B 10 CommandComplete "BEGIN"
+B 5 ReadyForQuery T
+F 18 ParameterSet "work_mem" "30MB"
+F 4 Sync
+B 4 ParameterSetComplete
+B 5 ReadyForQuery T
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '30MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery T
+F 13 Query "ROLLBACK"
+B 13 CommandComplete "ROLLBACK"
+B 5 ReadyForQuery I
+F 18 Query "SHOW work_mem"
+B 33 RowDescription 1 "work_mem" NNNN 0 NNNN 65535 -1 0
+B 14 DataRow 1 4 '12MB'
+B 9 CommandComplete "SHOW"
+B 5 ReadyForQuery I
+F 41 Query "SET SESSION AUTHORIZATION 'postgres'"
+B NN ErrorResponse S "ERROR" V "ERROR" C "55P02" M "parameter "session_authorization" cannot be set using SQL" F "SSSS" L "SSSS" R "SSSS" \x00
+B 5 ReadyForQuery I
+F 24 Query "SET ROLE 'postgres'"
+B NN ErrorResponse S "ERROR" V "ERROR" C "55P02" M "parameter "role" cannot be set using SQL" F "SSSS" L "SSSS" R "SSSS" \x00
+B 5 ReadyForQuery I
+F 46 ParameterSet "_pq_.protocol_managed_params" "doesnotexist"
+F 4 Sync
+B NN ErrorResponse S "ERROR" V "ERROR" C "42704" M "unrecognized configuration parameter "doesnotexist"" F "SSSS" L "SSSS" R "SSSS" \x00
+B 5 ReadyForQuery I
+F 71 ParameterSet "_pq_.protocol_managed_params" "work_mem,_pq_.protocol_managed_params"
+F 4 Sync
+B NN ErrorResponse S "ERROR" V "ERROR" C "22023" M "invalid value for parameter "_pq_.protocol_managed_params": "work_mem,_pq_.protocol_managed_params"" D "Parameter "_pq_.protocol_managed_params" is a protocol extension." F "SSSS" L "SSSS" R "SSSS" \x00
+B 5 ReadyForQuery I
+F 35 ParameterSet "_pq_.protocol_managed_params" """
+F 4 Sync
+B NN ErrorResponse S "ERROR" V "ERROR" C "22023" M "invalid value for parameter "_pq_.protocol_managed_params": """" D "List syntax is invalid." F "SSSS" L "SSSS" R "SSSS" \x00
+B 5 ReadyForQuery I
+F 4 Terminate
--
2.34.1