pgbench: Use PQExpBuffer to simplify code that constructs SQL.

Author: Fabien Coelho
Reviewed-by: Jeevan Ladhe
Discussion: https://www.postgresql.org/message-id/alpine.DEB.2.21.1910220826570.15559%40lancre
This commit is contained in:
Heikki Linnakangas 2020-09-30 10:58:09 +03:00
parent 300b6984a5
commit 9796f455c3
1 changed files with 95 additions and 97 deletions

View File

@ -603,7 +603,6 @@ static void doLog(TState *thread, CState *st,
StatsData *agg, bool skipped, double latency, double lag); StatsData *agg, bool skipped, double latency, double lag);
static void processXactStats(TState *thread, CState *st, instr_time *now, static void processXactStats(TState *thread, CState *st, instr_time *now,
bool skipped, StatsData *agg); bool skipped, StatsData *agg);
static void append_fillfactor(char *opts, int len);
static void addScript(ParsedScript script); static void addScript(ParsedScript script);
static void *threadRun(void *arg); static void *threadRun(void *arg);
static void finishCon(CState *st); static void finishCon(CState *st);
@ -3630,30 +3629,26 @@ initDropTables(PGconn *con)
static void static void
createPartitions(PGconn *con) createPartitions(PGconn *con)
{ {
char ff[64]; PQExpBufferData query;
ff[0] = '\0';
/*
* Per ddlinfo in initCreateTables, fillfactor is needed on table
* pgbench_accounts.
*/
append_fillfactor(ff, sizeof(ff));
/* we must have to create some partitions */ /* we must have to create some partitions */
Assert(partitions > 0); Assert(partitions > 0);
fprintf(stderr, "creating %d partitions...\n", partitions); fprintf(stderr, "creating %d partitions...\n", partitions);
initPQExpBuffer(&query);
for (int p = 1; p <= partitions; p++) for (int p = 1; p <= partitions; p++)
{ {
char query[256];
if (partition_method == PART_RANGE) if (partition_method == PART_RANGE)
{ {
int64 part_size = (naccounts * (int64) scale + partitions - 1) / partitions; int64 part_size = (naccounts * (int64) scale + partitions - 1) / partitions;
char minvalue[32],
maxvalue[32]; printfPQExpBuffer(&query,
"create%s table pgbench_accounts_%d\n"
" partition of pgbench_accounts\n"
" for values from (",
unlogged_tables ? " unlogged" : "", p);
/* /*
* For RANGE, we use open-ended partitions at the beginning and * For RANGE, we use open-ended partitions at the beginning and
@ -3662,34 +3657,39 @@ createPartitions(PGconn *con)
* scale, it is more generic and the performance is better. * scale, it is more generic and the performance is better.
*/ */
if (p == 1) if (p == 1)
sprintf(minvalue, "minvalue"); appendPQExpBufferStr(&query, "minvalue");
else else
sprintf(minvalue, INT64_FORMAT, (p - 1) * part_size + 1); appendPQExpBuffer(&query, INT64_FORMAT, (p - 1) * part_size + 1);
appendPQExpBufferStr(&query, ") to (");
if (p < partitions) if (p < partitions)
sprintf(maxvalue, INT64_FORMAT, p * part_size + 1); appendPQExpBuffer(&query, INT64_FORMAT, p * part_size + 1);
else else
sprintf(maxvalue, "maxvalue"); appendPQExpBufferStr(&query, "maxvalue");
snprintf(query, sizeof(query), appendPQExpBufferChar(&query, ')');
"create%s table pgbench_accounts_%d\n"
" partition of pgbench_accounts\n"
" for values from (%s) to (%s)%s\n",
unlogged_tables ? " unlogged" : "", p,
minvalue, maxvalue, ff);
} }
else if (partition_method == PART_HASH) else if (partition_method == PART_HASH)
snprintf(query, sizeof(query), printfPQExpBuffer(&query,
"create%s table pgbench_accounts_%d\n" "create%s table pgbench_accounts_%d\n"
" partition of pgbench_accounts\n" " partition of pgbench_accounts\n"
" for values with (modulus %d, remainder %d)%s\n", " for values with (modulus %d, remainder %d)",
unlogged_tables ? " unlogged" : "", p, unlogged_tables ? " unlogged" : "", p,
partitions, p - 1, ff); partitions, p - 1);
else /* cannot get there */ else /* cannot get there */
Assert(0); Assert(0);
executeStatement(con, query); /*
* Per ddlinfo in initCreateTables, fillfactor is needed on table
* pgbench_accounts.
*/
appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
executeStatement(con, query.data);
} }
termPQExpBuffer(&query);
} }
/* /*
@ -3743,63 +3743,50 @@ initCreateTables(PGconn *con)
} }
}; };
int i; int i;
PQExpBufferData query;
fprintf(stderr, "creating tables...\n"); fprintf(stderr, "creating tables...\n");
initPQExpBuffer(&query);
for (i = 0; i < lengthof(DDLs); i++) for (i = 0; i < lengthof(DDLs); i++)
{ {
char opts[256];
char buffer[256];
const struct ddlinfo *ddl = &DDLs[i]; const struct ddlinfo *ddl = &DDLs[i];
const char *cols;
/* Construct new create table statement. */ /* Construct new create table statement. */
opts[0] = '\0'; printfPQExpBuffer(&query, "create%s table %s(%s)",
unlogged_tables ? " unlogged" : "",
ddl->table,
(scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols);
/* Partition pgbench_accounts table */ /* Partition pgbench_accounts table */
if (partition_method != PART_NONE && strcmp(ddl->table, "pgbench_accounts") == 0) if (partition_method != PART_NONE && strcmp(ddl->table, "pgbench_accounts") == 0)
snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts), appendPQExpBuffer(&query,
" partition by %s (aid)", PARTITION_METHOD[partition_method]); " partition by %s (aid)", PARTITION_METHOD[partition_method]);
else if (ddl->declare_fillfactor) else if (ddl->declare_fillfactor)
{
/* fillfactor is only expected on actual tables */ /* fillfactor is only expected on actual tables */
append_fillfactor(opts, sizeof(opts)); appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
}
if (tablespace != NULL) if (tablespace != NULL)
{ {
char *escape_tablespace; char *escape_tablespace;
escape_tablespace = PQescapeIdentifier(con, tablespace, escape_tablespace = PQescapeIdentifier(con, tablespace, strlen(tablespace));
strlen(tablespace)); appendPQExpBuffer(&query, " tablespace %s", escape_tablespace);
snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
" tablespace %s", escape_tablespace);
PQfreemem(escape_tablespace); PQfreemem(escape_tablespace);
} }
cols = (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols; executeStatement(con, query.data);
snprintf(buffer, sizeof(buffer), "create%s table %s(%s)%s",
unlogged_tables ? " unlogged" : "",
ddl->table, cols, opts);
executeStatement(con, buffer);
} }
termPQExpBuffer(&query);
if (partition_method != PART_NONE) if (partition_method != PART_NONE)
createPartitions(con); createPartitions(con);
} }
/*
* add fillfactor percent option.
*
* XXX - As default is 100, it could be removed in this case.
*/
static void
append_fillfactor(char *opts, int len)
{
snprintf(opts + strlen(opts), len - strlen(opts),
" with (fillfactor=%d)", fillfactor);
}
/* /*
* Truncate away any old data, in one command in case there are foreign keys * Truncate away any old data, in one command in case there are foreign keys
*/ */
@ -3819,7 +3806,7 @@ initTruncateTables(PGconn *con)
static void static void
initGenerateDataClientSide(PGconn *con) initGenerateDataClientSide(PGconn *con)
{ {
char sql[256]; PQExpBufferData sql;
PGresult *res; PGresult *res;
int i; int i;
int64 k; int64 k;
@ -3845,6 +3832,8 @@ initGenerateDataClientSide(PGconn *con)
/* truncate away any old data */ /* truncate away any old data */
initTruncateTables(con); initTruncateTables(con);
initPQExpBuffer(&sql);
/* /*
* fill branches, tellers, accounts in that order in case foreign keys * fill branches, tellers, accounts in that order in case foreign keys
* already exist * already exist
@ -3852,19 +3841,19 @@ initGenerateDataClientSide(PGconn *con)
for (i = 0; i < nbranches * scale; i++) for (i = 0; i < nbranches * scale; i++)
{ {
/* "filler" column defaults to NULL */ /* "filler" column defaults to NULL */
snprintf(sql, sizeof(sql), printfPQExpBuffer(&sql,
"insert into pgbench_branches(bid,bbalance) values(%d,0)", "insert into pgbench_branches(bid,bbalance) values(%d,0)",
i + 1); i + 1);
executeStatement(con, sql); executeStatement(con, sql.data);
} }
for (i = 0; i < ntellers * scale; i++) for (i = 0; i < ntellers * scale; i++)
{ {
/* "filler" column defaults to NULL */ /* "filler" column defaults to NULL */
snprintf(sql, sizeof(sql), printfPQExpBuffer(&sql,
"insert into pgbench_tellers(tid,bid,tbalance) values (%d,%d,0)", "insert into pgbench_tellers(tid,bid,tbalance) values (%d,%d,0)",
i + 1, i / ntellers + 1); i + 1, i / ntellers + 1);
executeStatement(con, sql); executeStatement(con, sql.data);
} }
/* /*
@ -3885,10 +3874,10 @@ initGenerateDataClientSide(PGconn *con)
int64 j = k + 1; int64 j = k + 1;
/* "filler" column defaults to blank padded empty string */ /* "filler" column defaults to blank padded empty string */
snprintf(sql, sizeof(sql), printfPQExpBuffer(&sql,
INT64_FORMAT "\t" INT64_FORMAT "\t%d\t\n", INT64_FORMAT "\t" INT64_FORMAT "\t%d\t\n",
j, k / naccounts + 1, 0); j, k / naccounts + 1, 0);
if (PQputline(con, sql)) if (PQputline(con, sql.data))
{ {
pg_log_fatal("PQputline failed"); pg_log_fatal("PQputline failed");
exit(1); exit(1);
@ -3950,6 +3939,8 @@ initGenerateDataClientSide(PGconn *con)
exit(1); exit(1);
} }
termPQExpBuffer(&sql);
executeStatement(con, "commit"); executeStatement(con, "commit");
} }
@ -3963,7 +3954,7 @@ initGenerateDataClientSide(PGconn *con)
static void static void
initGenerateDataServerSide(PGconn *con) initGenerateDataServerSide(PGconn *con)
{ {
char sql[256]; PQExpBufferData sql;
fprintf(stderr, "generating data (server-side)...\n"); fprintf(stderr, "generating data (server-side)...\n");
@ -3976,24 +3967,28 @@ initGenerateDataServerSide(PGconn *con)
/* truncate away any old data */ /* truncate away any old data */
initTruncateTables(con); initTruncateTables(con);
snprintf(sql, sizeof(sql), initPQExpBuffer(&sql);
"insert into pgbench_branches(bid,bbalance) "
"select bid, 0 "
"from generate_series(1, %d) as bid", nbranches * scale);
executeStatement(con, sql);
snprintf(sql, sizeof(sql), printfPQExpBuffer(&sql,
"insert into pgbench_tellers(tid,bid,tbalance) " "insert into pgbench_branches(bid,bbalance) "
"select tid, (tid - 1) / %d + 1, 0 " "select bid, 0 "
"from generate_series(1, %d) as tid", ntellers, ntellers * scale); "from generate_series(1, %d) as bid", nbranches * scale);
executeStatement(con, sql); executeStatement(con, sql.data);
snprintf(sql, sizeof(sql), printfPQExpBuffer(&sql,
"insert into pgbench_accounts(aid,bid,abalance,filler) " "insert into pgbench_tellers(tid,bid,tbalance) "
"select aid, (aid - 1) / %d + 1, 0, '' " "select tid, (tid - 1) / %d + 1, 0 "
"from generate_series(1, " INT64_FORMAT ") as aid", "from generate_series(1, %d) as tid", ntellers, ntellers * scale);
naccounts, (int64) naccounts * scale); executeStatement(con, sql.data);
executeStatement(con, sql);
printfPQExpBuffer(&sql,
"insert into pgbench_accounts(aid,bid,abalance,filler) "
"select aid, (aid - 1) / %d + 1, 0, '' "
"from generate_series(1, " INT64_FORMAT ") as aid",
naccounts, (int64) naccounts * scale);
executeStatement(con, sql.data);
termPQExpBuffer(&sql);
executeStatement(con, "commit"); executeStatement(con, "commit");
} }
@ -4023,13 +4018,15 @@ initCreatePKeys(PGconn *con)
"alter table pgbench_accounts add primary key (aid)" "alter table pgbench_accounts add primary key (aid)"
}; };
int i; int i;
PQExpBufferData query;
fprintf(stderr, "creating primary keys...\n"); fprintf(stderr, "creating primary keys...\n");
initPQExpBuffer(&query);
for (i = 0; i < lengthof(DDLINDEXes); i++) for (i = 0; i < lengthof(DDLINDEXes); i++)
{ {
char buffer[256]; resetPQExpBuffer(&query);
appendPQExpBufferStr(&query, DDLINDEXes[i]);
strlcpy(buffer, DDLINDEXes[i], sizeof(buffer));
if (index_tablespace != NULL) if (index_tablespace != NULL)
{ {
@ -4037,13 +4034,14 @@ initCreatePKeys(PGconn *con)
escape_tablespace = PQescapeIdentifier(con, index_tablespace, escape_tablespace = PQescapeIdentifier(con, index_tablespace,
strlen(index_tablespace)); strlen(index_tablespace));
snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), appendPQExpBuffer(&query, " using index tablespace %s", escape_tablespace);
" using index tablespace %s", escape_tablespace);
PQfreemem(escape_tablespace); PQfreemem(escape_tablespace);
} }
executeStatement(con, buffer); executeStatement(con, query.data);
} }
termPQExpBuffer(&query);
} }
/* /*