08.02.2025 17:32, Álvaro Herrera пишет:
On 2025-Feb-07, Melanie Plageman wrote:
Okay, I've stared at this a bit, and it seems basically fine the way
it is (I might add a bit more whitespace, clean up the commit message,
etc). So I'm interested in committing it. I will admit that having
never committed anything to pgbench, I'm a bit nervous. So, give me a
couple days to work up the nerve.
Sounds good. I only wanted to say that I would use PQexecParams()
instead of PQexec() in the new function, avoiding the psprintf and
pfree, and also that initializing relkind to RELKIND_RELATION is strange
and probably unnecessary.
Let it be so. I made the suggested changes (patch v4 attached)
--
With best regards,
Sergey Tatarintsev,
PostgresPro
From cb363a01cdff72ccde303a1a67180e96bc9e74a8 Mon Sep 17 00:00:00 2001
From: Sergey Tatarintsev <s.tatarint...@postgrespro.ru>
Date: Mon, 3 Feb 2025 19:18:06 +0700
Subject: [PATCH] Fix pgbench client-side data generation for partitioned
tables
Client-side data generation cannot perform COPY WITH (FREEZE = ON) on partitioned
tables except pgbench_accounts.
Patch disables FREEZE for any non-regular tables
---
src/bin/pgbench/pgbench.c | 37 ++++++++++++++++++++++++++++---------
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 40592e6260..8b867b45a7 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -53,6 +53,7 @@
#include <sys/select.h>
#endif
+#include "catalog/pg_class.h"
#include "common/int.h"
#include "common/logging.h"
#include "common/pg_prng.h"
@@ -848,6 +849,30 @@ static const PsqlScanCallbacks pgbench_callbacks = {
NULL, /* don't need get_variable functionality */
};
+static char
+get_table_relkind(PGconn *con, const char *table)
+{
+ PGresult *res;
+ char *val;
+ char relkind;
+ const char *sql = "SELECT relkind FROM pg_catalog.pg_class WHERE oid=$1::pg_catalog.regclass";
+ const char *params[1] = {table};
+
+ res = PQexecParams(con, sql, 1, NULL, params, NULL, NULL, 0);
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ pg_log_error("query failed: %s", PQerrorMessage(con));
+ pg_log_error_detail("Query was: %s", sql);
+ exit(1);
+ }
+ val = PQgetvalue(res, 0, 0);
+ Assert(strlen(val) == 1);
+ relkind = val[0];
+ PQclear(res);
+
+ return relkind;
+}
+
static inline pg_time_usec_t
pg_time_now(void)
{
@@ -4962,16 +4987,10 @@ initPopulateTable(PGconn *con, const char *table, int64 base,
initPQExpBuffer(&sql);
- /*
- * Use COPY with FREEZE on v14 and later for all the tables except
- * pgbench_accounts when it is partitioned.
- */
- if (PQserverVersion(con) >= 140000)
- {
- if (strcmp(table, "pgbench_accounts") != 0 ||
- partitions == 0)
+ /* Use COPY with FREEZE on v14 and later for all regular tables */
+ if ((PQserverVersion(con) >= 140000) && get_table_relkind(con, table) == RELKIND_RELATION)
copy_statement_fmt = "copy %s from stdin with (freeze on)";
- }
+
n = pg_snprintf(copy_statement, sizeof(copy_statement), copy_statement_fmt, table);
if (n >= sizeof(copy_statement))
--
2.43.0