Skip to content

Commit 9796f45

Browse files
committed
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
1 parent 300b698 commit 9796f45

File tree

1 file changed

+98
-100
lines changed

1 file changed

+98
-100
lines changed

src/bin/pgbench/pgbench.c

Lines changed: 98 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,6 @@ static void doLog(TState *thread, CState *st,
603603
StatsData *agg, bool skipped, double latency, double lag);
604604
static void processXactStats(TState *thread, CState *st, instr_time *now,
605605
bool skipped, StatsData *agg);
606-
static void append_fillfactor(char *opts, int len);
607606
static void addScript(ParsedScript script);
608607
static void *threadRun(void *arg);
609608
static void finishCon(CState *st);
@@ -3630,30 +3629,26 @@ initDropTables(PGconn *con)
36303629
static void
36313630
createPartitions(PGconn *con)
36323631
{
3633-
char ff[64];
3634-
3635-
ff[0] = '\0';
3636-
3637-
/*
3638-
* Per ddlinfo in initCreateTables, fillfactor is needed on table
3639-
* pgbench_accounts.
3640-
*/
3641-
append_fillfactor(ff, sizeof(ff));
3632+
PQExpBufferData query;
36423633

36433634
/* we must have to create some partitions */
36443635
Assert(partitions > 0);
36453636

36463637
fprintf(stderr, "creating %d partitions...\n", partitions);
36473638

3639+
initPQExpBuffer(&query);
3640+
36483641
for (int p = 1; p <= partitions; p++)
36493642
{
3650-
char query[256];
3651-
36523643
if (partition_method == PART_RANGE)
36533644
{
36543645
int64 part_size = (naccounts * (int64) scale + partitions - 1) / partitions;
3655-
char minvalue[32],
3656-
maxvalue[32];
3646+
3647+
printfPQExpBuffer(&query,
3648+
"create%s table pgbench_accounts_%d\n"
3649+
" partition of pgbench_accounts\n"
3650+
" for values from (",
3651+
unlogged_tables ? " unlogged" : "", p);
36573652

36583653
/*
36593654
* For RANGE, we use open-ended partitions at the beginning and
@@ -3662,34 +3657,39 @@ createPartitions(PGconn *con)
36623657
* scale, it is more generic and the performance is better.
36633658
*/
36643659
if (p == 1)
3665-
sprintf(minvalue, "minvalue");
3660+
appendPQExpBufferStr(&query, "minvalue");
36663661
else
3667-
sprintf(minvalue, INT64_FORMAT, (p - 1) * part_size + 1);
3662+
appendPQExpBuffer(&query, INT64_FORMAT, (p - 1) * part_size + 1);
3663+
3664+
appendPQExpBufferStr(&query, ") to (");
36683665

36693666
if (p < partitions)
3670-
sprintf(maxvalue, INT64_FORMAT, p * part_size + 1);
3667+
appendPQExpBuffer(&query, INT64_FORMAT, p * part_size + 1);
36713668
else
3672-
sprintf(maxvalue, "maxvalue");
3673-
3674-
snprintf(query, sizeof(query),
3675-
"create%s table pgbench_accounts_%d\n"
3676-
" partition of pgbench_accounts\n"
3677-
" for values from (%s) to (%s)%s\n",
3678-
unlogged_tables ? " unlogged" : "", p,
3679-
minvalue, maxvalue, ff);
3669+
appendPQExpBufferStr(&query, "maxvalue");
3670+
3671+
appendPQExpBufferChar(&query, ')');
36803672
}
36813673
else if (partition_method == PART_HASH)
3682-
snprintf(query, sizeof(query),
3683-
"create%s table pgbench_accounts_%d\n"
3684-
" partition of pgbench_accounts\n"
3685-
" for values with (modulus %d, remainder %d)%s\n",
3686-
unlogged_tables ? " unlogged" : "", p,
3687-
partitions, p - 1, ff);
3674+
printfPQExpBuffer(&query,
3675+
"create%s table pgbench_accounts_%d\n"
3676+
" partition of pgbench_accounts\n"
3677+
" for values with (modulus %d, remainder %d)",
3678+
unlogged_tables ? " unlogged" : "", p,
3679+
partitions, p - 1);
36883680
else /* cannot get there */
36893681
Assert(0);
36903682

3691-
executeStatement(con, query);
3683+
/*
3684+
* Per ddlinfo in initCreateTables, fillfactor is needed on table
3685+
* pgbench_accounts.
3686+
*/
3687+
appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
3688+
3689+
executeStatement(con, query.data);
36923690
}
3691+
3692+
termPQExpBuffer(&query);
36933693
}
36943694

36953695
/*
@@ -3743,63 +3743,50 @@ initCreateTables(PGconn *con)
37433743
}
37443744
};
37453745
int i;
3746+
PQExpBufferData query;
37463747

37473748
fprintf(stderr, "creating tables...\n");
37483749

3750+
initPQExpBuffer(&query);
3751+
37493752
for (i = 0; i < lengthof(DDLs); i++)
37503753
{
3751-
char opts[256];
3752-
char buffer[256];
37533754
const struct ddlinfo *ddl = &DDLs[i];
3754-
const char *cols;
37553755

37563756
/* Construct new create table statement. */
3757-
opts[0] = '\0';
3757+
printfPQExpBuffer(&query, "create%s table %s(%s)",
3758+
unlogged_tables ? " unlogged" : "",
3759+
ddl->table,
3760+
(scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols);
37583761

37593762
/* Partition pgbench_accounts table */
37603763
if (partition_method != PART_NONE && strcmp(ddl->table, "pgbench_accounts") == 0)
3761-
snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
3762-
" partition by %s (aid)", PARTITION_METHOD[partition_method]);
3764+
appendPQExpBuffer(&query,
3765+
" partition by %s (aid)", PARTITION_METHOD[partition_method]);
37633766
else if (ddl->declare_fillfactor)
3767+
{
37643768
/* fillfactor is only expected on actual tables */
3765-
append_fillfactor(opts, sizeof(opts));
3769+
appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
3770+
}
37663771

37673772
if (tablespace != NULL)
37683773
{
37693774
char *escape_tablespace;
37703775

3771-
escape_tablespace = PQescapeIdentifier(con, tablespace,
3772-
strlen(tablespace));
3773-
snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
3774-
" tablespace %s", escape_tablespace);
3776+
escape_tablespace = PQescapeIdentifier(con, tablespace, strlen(tablespace));
3777+
appendPQExpBuffer(&query, " tablespace %s", escape_tablespace);
37753778
PQfreemem(escape_tablespace);
37763779
}
37773780

3778-
cols = (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols;
3779-
3780-
snprintf(buffer, sizeof(buffer), "create%s table %s(%s)%s",
3781-
unlogged_tables ? " unlogged" : "",
3782-
ddl->table, cols, opts);
3783-
3784-
executeStatement(con, buffer);
3781+
executeStatement(con, query.data);
37853782
}
37863783

3784+
termPQExpBuffer(&query);
3785+
37873786
if (partition_method != PART_NONE)
37883787
createPartitions(con);
37893788
}
37903789

3791-
/*
3792-
* add fillfactor percent option.
3793-
*
3794-
* XXX - As default is 100, it could be removed in this case.
3795-
*/
3796-
static void
3797-
append_fillfactor(char *opts, int len)
3798-
{
3799-
snprintf(opts + strlen(opts), len - strlen(opts),
3800-
" with (fillfactor=%d)", fillfactor);
3801-
}
3802-
38033790
/*
38043791
* Truncate away any old data, in one command in case there are foreign keys
38053792
*/
@@ -3819,7 +3806,7 @@ initTruncateTables(PGconn *con)
38193806
static void
38203807
initGenerateDataClientSide(PGconn *con)
38213808
{
3822-
char sql[256];
3809+
PQExpBufferData sql;
38233810
PGresult *res;
38243811
int i;
38253812
int64 k;
@@ -3845,26 +3832,28 @@ initGenerateDataClientSide(PGconn *con)
38453832
/* truncate away any old data */
38463833
initTruncateTables(con);
38473834

3835+
initPQExpBuffer(&sql);
3836+
38483837
/*
38493838
* fill branches, tellers, accounts in that order in case foreign keys
38503839
* already exist
38513840
*/
38523841
for (i = 0; i < nbranches * scale; i++)
38533842
{
38543843
/* "filler" column defaults to NULL */
3855-
snprintf(sql, sizeof(sql),
3856-
"insert into pgbench_branches(bid,bbalance) values(%d,0)",
3857-
i + 1);
3858-
executeStatement(con, sql);
3844+
printfPQExpBuffer(&sql,
3845+
"insert into pgbench_branches(bid,bbalance) values(%d,0)",
3846+
i + 1);
3847+
executeStatement(con, sql.data);
38593848
}
38603849

38613850
for (i = 0; i < ntellers * scale; i++)
38623851
{
38633852
/* "filler" column defaults to NULL */
3864-
snprintf(sql, sizeof(sql),
3865-
"insert into pgbench_tellers(tid,bid,tbalance) values (%d,%d,0)",
3866-
i + 1, i / ntellers + 1);
3867-
executeStatement(con, sql);
3853+
printfPQExpBuffer(&sql,
3854+
"insert into pgbench_tellers(tid,bid,tbalance) values (%d,%d,0)",
3855+
i + 1, i / ntellers + 1);
3856+
executeStatement(con, sql.data);
38683857
}
38693858

38703859
/*
@@ -3885,10 +3874,10 @@ initGenerateDataClientSide(PGconn *con)
38853874
int64 j = k + 1;
38863875

38873876
/* "filler" column defaults to blank padded empty string */
3888-
snprintf(sql, sizeof(sql),
3889-
INT64_FORMAT "\t" INT64_FORMAT "\t%d\t\n",
3890-
j, k / naccounts + 1, 0);
3891-
if (PQputline(con, sql))
3877+
printfPQExpBuffer(&sql,
3878+
INT64_FORMAT "\t" INT64_FORMAT "\t%d\t\n",
3879+
j, k / naccounts + 1, 0);
3880+
if (PQputline(con, sql.data))
38923881
{
38933882
pg_log_fatal("PQputline failed");
38943883
exit(1);
@@ -3950,6 +3939,8 @@ initGenerateDataClientSide(PGconn *con)
39503939
exit(1);
39513940
}
39523941

3942+
termPQExpBuffer(&sql);
3943+
39533944
executeStatement(con, "commit");
39543945
}
39553946

@@ -3963,7 +3954,7 @@ initGenerateDataClientSide(PGconn *con)
39633954
static void
39643955
initGenerateDataServerSide(PGconn *con)
39653956
{
3966-
char sql[256];
3957+
PQExpBufferData sql;
39673958

39683959
fprintf(stderr, "generating data (server-side)...\n");
39693960

@@ -3976,24 +3967,28 @@ initGenerateDataServerSide(PGconn *con)
39763967
/* truncate away any old data */
39773968
initTruncateTables(con);
39783969

3979-
snprintf(sql, sizeof(sql),
3980-
"insert into pgbench_branches(bid,bbalance) "
3981-
"select bid, 0 "
3982-
"from generate_series(1, %d) as bid", nbranches * scale);
3983-
executeStatement(con, sql);
3984-
3985-
snprintf(sql, sizeof(sql),
3986-
"insert into pgbench_tellers(tid,bid,tbalance) "
3987-
"select tid, (tid - 1) / %d + 1, 0 "
3988-
"from generate_series(1, %d) as tid", ntellers, ntellers * scale);
3989-
executeStatement(con, sql);
3990-
3991-
snprintf(sql, sizeof(sql),
3992-
"insert into pgbench_accounts(aid,bid,abalance,filler) "
3993-
"select aid, (aid - 1) / %d + 1, 0, '' "
3994-
"from generate_series(1, " INT64_FORMAT ") as aid",
3995-
naccounts, (int64) naccounts * scale);
3996-
executeStatement(con, sql);
3970+
initPQExpBuffer(&sql);
3971+
3972+
printfPQExpBuffer(&sql,
3973+
"insert into pgbench_branches(bid,bbalance) "
3974+
"select bid, 0 "
3975+
"from generate_series(1, %d) as bid", nbranches * scale);
3976+
executeStatement(con, sql.data);
3977+
3978+
printfPQExpBuffer(&sql,
3979+
"insert into pgbench_tellers(tid,bid,tbalance) "
3980+
"select tid, (tid - 1) / %d + 1, 0 "
3981+
"from generate_series(1, %d) as tid", ntellers, ntellers * scale);
3982+
executeStatement(con, sql.data);
3983+
3984+
printfPQExpBuffer(&sql,
3985+
"insert into pgbench_accounts(aid,bid,abalance,filler) "
3986+
"select aid, (aid - 1) / %d + 1, 0, '' "
3987+
"from generate_series(1, " INT64_FORMAT ") as aid",
3988+
naccounts, (int64) naccounts * scale);
3989+
executeStatement(con, sql.data);
3990+
3991+
termPQExpBuffer(&sql);
39973992

39983993
executeStatement(con, "commit");
39993994
}
@@ -4023,27 +4018,30 @@ initCreatePKeys(PGconn *con)
40234018
"alter table pgbench_accounts add primary key (aid)"
40244019
};
40254020
int i;
4021+
PQExpBufferData query;
40264022

40274023
fprintf(stderr, "creating primary keys...\n");
4024+
initPQExpBuffer(&query);
4025+
40284026
for (i = 0; i < lengthof(DDLINDEXes); i++)
40294027
{
4030-
char buffer[256];
4031-
4032-
strlcpy(buffer, DDLINDEXes[i], sizeof(buffer));
4028+
resetPQExpBuffer(&query);
4029+
appendPQExpBufferStr(&query, DDLINDEXes[i]);
40334030

40344031
if (index_tablespace != NULL)
40354032
{
40364033
char *escape_tablespace;
40374034

40384035
escape_tablespace = PQescapeIdentifier(con, index_tablespace,
40394036
strlen(index_tablespace));
4040-
snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer),
4041-
" using index tablespace %s", escape_tablespace);
4037+
appendPQExpBuffer(&query, " using index tablespace %s", escape_tablespace);
40424038
PQfreemem(escape_tablespace);
40434039
}
40444040

4045-
executeStatement(con, buffer);
4041+
executeStatement(con, query.data);
40464042
}
4043+
4044+
termPQExpBuffer(&query);
40474045
}
40484046

40494047
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy