30 #if defined(WIN32) && FD_SETSIZE < 1024
31 #error FD_SETSIZE needs to have been increased
46 #if defined(HAVE_PPOLL) && !defined(PGBENCH_USE_SELECT)
47 #define POLL_USING_PPOLL
52 #define POLL_USING_SELECT
73 #define M_PI 3.14159265358979323846
76 #define ERRCODE_T_R_SERIALIZATION_FAILURE "40001"
77 #define ERRCODE_T_R_DEADLOCK_DETECTED "40P01"
78 #define ERRCODE_UNDEFINED_TABLE "42P01"
83 #define FNV_PRIME UINT64CONST(0x100000001b3)
84 #define FNV_OFFSET_BASIS UINT64CONST(0xcbf29ce484222325)
85 #define MM2_MUL UINT64CONST(0xc6a4a7935bd1e995)
86 #define MM2_MUL_TIMES_8 UINT64CONST(0x35253c9ade8f4ca8)
93 #ifdef POLL_USING_PPOLL
94 #define SOCKET_WAIT_METHOD "ppoll"
105 #ifdef POLL_USING_SELECT
106 #define SOCKET_WAIT_METHOD "select"
123 #define GETERRNO() (_dosmaperr(GetLastError()), errno)
124 #define THREAD_T HANDLE
125 #define THREAD_FUNC_RETURN_TYPE unsigned
126 #define THREAD_FUNC_RETURN return 0
127 #define THREAD_FUNC_CC __stdcall
128 #define THREAD_CREATE(handle, function, arg) \
129 ((*(handle) = (HANDLE) _beginthreadex(NULL, 0, (function), (arg), 0, NULL)) == 0 ? errno : 0)
130 #define THREAD_JOIN(handle) \
131 (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0 ? \
132 GETERRNO() : CloseHandle(handle) ? 0 : GETERRNO())
133 #define THREAD_BARRIER_T SYNCHRONIZATION_BARRIER
134 #define THREAD_BARRIER_INIT(barrier, n) \
135 (InitializeSynchronizationBarrier((barrier), (n), 0) ? 0 : GETERRNO())
136 #define THREAD_BARRIER_WAIT(barrier) \
137 EnterSynchronizationBarrier((barrier), \
138 SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
139 #define THREAD_BARRIER_DESTROY(barrier)
143 #define THREAD_T pthread_t
144 #define THREAD_FUNC_RETURN_TYPE void *
145 #define THREAD_FUNC_RETURN return NULL
146 #define THREAD_FUNC_CC
147 #define THREAD_CREATE(handle, function, arg) \
148 pthread_create((handle), NULL, (function), (arg))
149 #define THREAD_JOIN(handle) \
150 pthread_join((handle), NULL)
151 #define THREAD_BARRIER_T pthread_barrier_t
152 #define THREAD_BARRIER_INIT(barrier, n) \
153 pthread_barrier_init((barrier), NULL, (n))
154 #define THREAD_BARRIER_WAIT(barrier) pthread_barrier_wait((barrier))
155 #define THREAD_BARRIER_DESTROY(barrier) pthread_barrier_destroy((barrier))
162 #define DEFAULT_INIT_STEPS "dtgvp"
163 #define ALL_INIT_STEPS "dtgGvpf"
165 #define LOG_STEP_SECONDS 5
166 #define DEFAULT_NXACTS 10
168 #define MIN_GAUSSIAN_PARAM 2.0
170 #define MIN_ZIPFIAN_PARAM 1.001
171 #define MAX_ZIPFIAN_PARAM 1000.0
246 #define naccounts 100000
255 #define SCALE_32BIT_THRESHOLD 20000
310 #define VARIABLES_ALLOC_MARGIN 8
347 #define MAX_SCRIPTS 128
348 #define SHELL_COMMAND_SIZE 256
661 int64 throttle_trigger;
678 #define SQL_COMMAND 1
679 #define META_COMMAND 2
714 static const char *
const QUERYMODE[] = {
"simple",
"extended",
"prepared"};
784 "<builtin: TPC-B (sort of)>",
788 "\\set delta random(-5000, 5000)\n"
790 "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
791 "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
792 "UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\n"
793 "UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\n"
794 "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
799 "<builtin: simple update>",
803 "\\set delta random(-5000, 5000)\n"
805 "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
806 "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
807 "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
812 "<builtin: select only>",
814 "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
828 StatsData *agg,
bool skipped,
double latency,
double lag);
867 #define PG_TIME_GET_DOUBLE(t) (0.000001 * (t))
872 printf(
"%s is a benchmarking tool for PostgreSQL.\n\n"
874 " %s [OPTION]... [DBNAME]\n"
875 "\nInitialization options:\n"
876 " -i, --initialize invokes initialization mode\n"
878 " run selected initialization steps, in the specified order\n"
879 " d: drop any existing pgbench tables\n"
880 " t: create the tables used by the standard pgbench scenario\n"
881 " g: generate data, client-side\n"
882 " G: generate data, server-side\n"
883 " v: invoke VACUUM on the standard tables\n"
884 " p: create primary key indexes on the standard tables\n"
885 " f: create foreign keys between the standard tables\n"
886 " -F, --fillfactor=NUM set fill factor\n"
887 " -n, --no-vacuum do not run VACUUM during initialization\n"
888 " -q, --quiet quiet logging (one message each 5 seconds)\n"
889 " -s, --scale=NUM scaling factor\n"
890 " --foreign-keys create foreign key constraints between tables\n"
891 " --index-tablespace=TABLESPACE\n"
892 " create indexes in the specified tablespace\n"
893 " --partition-method=(range|hash)\n"
894 " partition pgbench_accounts with this method (default: range)\n"
895 " --partitions=NUM partition pgbench_accounts into NUM parts (default: 0)\n"
896 " --tablespace=TABLESPACE create tables in the specified tablespace\n"
897 " --unlogged-tables create tables as unlogged tables\n"
898 "\nOptions to select what to run:\n"
899 " -b, --builtin=NAME[@W] add builtin script NAME weighted at W (default: 1)\n"
900 " (use \"-b list\" to list available scripts)\n"
901 " -f, --file=FILENAME[@W] add script FILENAME weighted at W (default: 1)\n"
902 " -N, --skip-some-updates skip updates of pgbench_tellers and pgbench_branches\n"
903 " (same as \"-b simple-update\")\n"
904 " -S, --select-only perform SELECT-only transactions\n"
905 " (same as \"-b select-only\")\n"
906 "\nBenchmarking options:\n"
907 " -c, --client=NUM number of concurrent database clients (default: 1)\n"
908 " -C, --connect establish new connection for each transaction\n"
909 " -D, --define=VARNAME=VALUE\n"
910 " define variable for use by custom script\n"
911 " -j, --jobs=NUM number of threads (default: 1)\n"
912 " -l, --log write transaction times to log file\n"
913 " -L, --latency-limit=NUM count transactions lasting more than NUM ms as late\n"
914 " -M, --protocol=simple|extended|prepared\n"
915 " protocol for submitting queries (default: simple)\n"
916 " -n, --no-vacuum do not run VACUUM before tests\n"
917 " -P, --progress=NUM show thread progress report every NUM seconds\n"
918 " -r, --report-per-command report latencies, failures, and retries per command\n"
919 " -R, --rate=NUM target rate in transactions per second\n"
920 " -s, --scale=NUM report this scale factor in output\n"
921 " -t, --transactions=NUM number of transactions each client runs (default: 10)\n"
922 " -T, --time=NUM duration of benchmark test in seconds\n"
923 " -v, --vacuum-all vacuum all four standard tables before tests\n"
924 " --aggregate-interval=NUM aggregate data over NUM seconds\n"
925 " --exit-on-abort exit when any client is aborted\n"
926 " --failures-detailed report the failures grouped by basic types\n"
927 " --log-prefix=PREFIX prefix for transaction time log file\n"
928 " (default: \"pgbench_log\")\n"
929 " --max-tries=NUM max number of tries to run transaction (default: 1)\n"
930 " --progress-timestamp use Unix epoch timestamps for progress\n"
931 " --random-seed=SEED set random seed (\"time\", \"rand\", integer)\n"
932 " --sampling-rate=NUM fraction of transactions to log (e.g., 0.01 for 1%%)\n"
933 " --show-script=NAME show builtin script code, then exit\n"
934 " --verbose-errors print messages of all errors\n"
935 "\nCommon options:\n"
936 " --debug print debugging output\n"
937 " -d, --dbname=DBNAME database name to connect to\n"
938 " -h, --host=HOSTNAME database server host or socket directory\n"
939 " -p, --port=PORT database server port number\n"
940 " -U, --username=USERNAME connect as specified database user\n"
941 " -V, --version output version information, then exit\n"
942 " -?, --help show this help, then exit\n"
944 "Report bugs to <%s>.\n"
945 "%s home page: <%s>\n",
953 const char *ptr =
str;
956 while (*ptr && isspace((
unsigned char) *ptr))
960 if (*ptr ==
'+' || *ptr ==
'-')
964 if (*ptr && !isdigit((
unsigned char) *ptr))
968 while (*ptr && isdigit((
unsigned char) *ptr))
990 const char *ptr =
str;
1003 while (*ptr && isspace((
unsigned char) *ptr))
1012 else if (*ptr ==
'+')
1016 if (
unlikely(!isdigit((
unsigned char) *ptr)))
1017 goto invalid_syntax;
1020 while (*ptr && isdigit((
unsigned char) *ptr))
1022 int8 digit = (*ptr++ -
'0');
1030 while (*ptr !=
'\0' && isspace((
unsigned char) *ptr))
1034 goto invalid_syntax;
1064 *dv = strtod(
str, &end);
1122 cut = exp(-parameter);
1129 Assert((1.0 - cut) != 0.0);
1130 rand = -log(cut + (1.0 - cut) * uniform) / parameter;
1132 return min + (int64) ((max - min + 1) * rand);
1162 while (stdev < -parameter || stdev >= parameter);
1165 rand = (stdev + parameter) / (parameter * 2.0);
1168 return min + (int64) ((max - min + 1) * rand);
1190 return (int64) (-log(uniform) * center + 0.5);
1203 double b = pow(2.0, s - 1.0);
1219 x = floor(pow(u, -1.0 / (s - 1.0)));
1221 t = pow(1.0 + 1.0 /
x, s - 1.0);
1223 if (v *
x * (t - 1.0) / (
b - 1.0) <= t /
b &&
x <= n)
1233 int64 n = max - min + 1;
1251 for (
i = 0;
i < 8; ++
i)
1256 result = result ^ octet;
1273 uint64 k = (uint64)
val;
1286 return (int64) result;
1303 permute(
const int64
val,
const int64 isize,
const int64 seed)
1320 size = (uint64) isize;
1325 mask = (((uint64) 1) << masklen) - 1;
1356 for (
i = 0;
i < 6;
i++)
1367 v = ((v * m) ^ r) & mask;
1368 v = ((v << 1) & mask) | (v >> (masklen - 1));
1377 t = ((t * m) ^ r) & mask;
1378 t = ((t << 1) & mask) | (t >> (masklen - 1));
1405 if (ss->
count == 0 || val < ss->min)
1468 stats->
retries += (tries - 1);
1494 pg_fatal(
"unexpected error status: %d", estatus);
1543 #define PARAMS_ARRAY_SIZE 7
1548 keywords[0] =
"host";
1550 keywords[1] =
"port";
1552 keywords[2] =
"user";
1554 keywords[3] =
"password";
1556 keywords[4] =
"dbname";
1558 keywords[5] =
"fallback_application_name";
1609 if (variables->
nvars <= 0)
1634 char stringform[64];
1646 snprintf(stringform,
sizeof(stringform),
"NULL");
1648 snprintf(stringform,
sizeof(stringform),
1651 snprintf(stringform,
sizeof(stringform),
1654 snprintf(stringform,
sizeof(stringform),
1671 slen = strlen(var->
svalue);
1715 pg_log_error(
"malformed variable \"%s\" value: \"%s\"",
1740 const unsigned char *ptr = (
const unsigned char *)
name;
1748 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1758 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1759 "_0123456789", *ptr) != NULL)
1776 needed += variables->
nvars;
1812 var = &(variables->
vars[variables->
nvars]);
1896 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1897 "_", sql[
i]) != NULL)
1903 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1904 "_0123456789", sql[
i]) != NULL)
1908 memcpy(
name, &sql[1],
i - 1);
1918 int valueln = strlen(
value);
1922 size_t offset = param - *sql;
1925 param = *sql + offset;
1929 memmove(param + valueln, param +
len, strlen(param +
len) + 1);
1930 memcpy(param,
value, valueln);
1932 return param + valueln;
1943 while ((p = strchr(p,
':')) != NULL)
1973 const char **params)
1977 for (
i = 0;
i < command->
argc - 1;
i++)
2008 *bval = pval->
u.
bval;
2031 return pval->
u.
bval;
2033 return pval->
u.
ival != 0;
2035 return pval->
u.
dval != 0.0;
2049 *ival = pval->
u.
ival;
2054 double dval = rint(pval->
u.
dval);
2061 *ival = (int64) dval;
2077 *dval = pval->
u.
dval;
2082 *dval = (double) pval->
u.
ival;
2227 if (
args->next == NULL)
2242 #define MAX_FARGS 16
2256 bool has_null =
false;
2264 for (nargs = 0; nargs <
MAX_FARGS && l != NULL; nargs++, l = l->
next)
2512 double d = varg->
u.
dval;
2527 fprintf(stderr,
"debug(script=%d,command=%d): ",
2533 fprintf(stderr,
"boolean %s\n", varg->
u.
bval ?
"true" :
"false");
2537 fprintf(stderr,
"double %.*g\n", DBL_DIG, varg->
u.
dval);
2596 for (
i = 0;
i < nargs;
i++)
2610 for (
i = 1;
i < nargs;
i++)
2617 extremum =
Min(extremum, dval);
2619 extremum =
Max(extremum, dval);
2629 for (
i = 1;
i < nargs;
i++)
2636 extremum =
Min(extremum, ival);
2638 extremum =
Max(extremum, ival);
2693 pg_log_error(
"gaussian parameter must be at least %f (not %f)",
2700 imin, imax, param));
2706 pg_log_error(
"zipfian parameter must be in range [%.3f, %.0f] (not %f)",
2718 pg_log_error(
"exponential parameter must be greater than zero (not %f)",
2725 imin, imax, param));
2803 pg_log_error(
"permute size parameter must be greater than zero");
2839 switch (expr->
etype)
2860 *retval = var->
value;
2872 pg_fatal(
"unexpected enode type in evaluation: %d", expr->
etype);
2940 for (
i = 0;
i < argc;
i++)
2945 if (argv[
i][0] !=
':')
2949 else if (argv[
i][1] ==
':')
2955 pg_log_error(
"%s: undefined variable \"%s\"", argv[0], argv[
i]);
2959 arglen = strlen(
arg);
2962 pg_log_error(
"%s: shell command is too long", argv[0]);
2967 command[
len++] =
' ';
2968 memcpy(command +
len,
arg, arglen);
2972 command[
len] =
'\0';
2979 if (system(command))
2982 pg_log_error(
"%s: could not launch shell command", argv[0]);
2989 if ((fp = popen(command,
"r")) == NULL)
2991 pg_log_error(
"%s: could not launch shell command", argv[0]);
2994 if (fgets(
res,
sizeof(
res), fp) == NULL)
2997 pg_log_error(
"%s: could not read result of shell command", argv[0]);
3003 pg_log_error(
"%s: could not run shell command: %m", argv[0]);
3008 retval = (int) strtol(
res, &endptr, 10);
3009 while (*endptr !=
'\0' && isspace((
unsigned char) *endptr))
3011 if (*
res ==
'\0' || *endptr !=
'\0')
3013 pg_log_error(
"%s: shell command must return an integer (not \"%s\")", argv[0],
res);
3019 pg_log_debug(
"%s: shell parameter name: \"%s\", value: \"%s\"", argv[0], argv[1],
res);
3030 pg_log_error(
"client %d aborted in command %d (%s) of script %d; %s",
3041 pg_log_info(
"client %d got an error in command %d (SQL) of script %d; %s",
3079 for (numcmds = 0; script->
commands[numcmds] != NULL; numcmds++)
3106 command->
argv[0], command->
argc - 1, NULL);
3141 for (
j = st->
command + 1; commands[
j] != NULL;
j++)
3172 const char *sql = command->
argv[0];
3179 NULL, params, NULL, NULL, 0);
3190 params, NULL, NULL, 0);
3210 if (sqlState != NULL)
3263 is_last = (next_res == NULL);
3271 pg_log_error(
"client %d script %d command %d query %d: expected one row, got %d",
3286 pg_log_error(
"client %d script %d command %d query %d: expected one row, got %d",
3291 else if (meta ==
META_ASET && ntuples <= 0)
3303 if (*varprefix !=
'\0')
3304 varname =
psprintf(
"%s%s", varprefix, varname);
3311 pg_log_error(
"client %d script %d command %d query %d: error storing into variable %s",
3317 if (*varprefix !=
'\0')
3325 pg_log_debug(
"client %d pipeline ending, ongoing syncs: %d",
3329 pg_log_error(
"client %d failed to exit pipeline mode: %s", st->
id,
3347 pg_log_error(
"client %d script %d aborted in command %d query %d: %s",
3388 if (*argv[1] ==
':')
3390 if ((var =
getVariable(variables, argv[1] + 1)) == NULL)
3392 pg_log_error(
"%s: undefined variable \"%s\"", argv[0], argv[1] + 1);
3399 if (usec == 0 && !isdigit((
unsigned char) *var))
3401 pg_log_error(
"%s: invalid sleep time \"%s\" for variable \"%s\"",
3402 argv[0], var, argv[1] + 1);
3407 usec = atoi(argv[1]);
3479 pg_log_error(
"client %d aborted: failed to send a pipeline sync",
3502 pg_log_error(
"client %d aborted: failed to exit pipeline mode for rolling back the failed transaction",
3538 pg_log_error(
"unexpected transaction status %d", tx_status);
3562 "repeats the transaction after the error" :
3563 "ends the failed transaction"));
3642 if (st->
con == NULL)
3652 pg_log_error(
"client %d aborted while establishing connection", st->
id);
3760 if (now < st->txn_scheduled)
3777 if (command == NULL)
3783 pg_log_error(
"client %d aborted: end of script reached with pipeline open",
3806 commandFailed(st,
"gset",
"\\gset is not allowed in pipeline mode");
3812 commandFailed(st,
"aset",
"\\aset is not allowed in pipeline mode");
3966 commandFailed(st,
"SQL",
"perhaps the backend died while processing");
4000 if (now < st->sleep_until)
4064 pg_log_error(
"client %d aborted: failed to send sql command for rolling back the failed transaction",
4083 pg_log_error(
"perhaps the backend died while processing");
4085 pg_log_error(
"client %d aborted while receiving the transaction status", st->
id);
4101 pg_log_error(
"client %d aborted while rolling back the transaction after an error; perhaps the backend died while processing",
4130 pg_log_error(
"client %d aborted while rolling back the transaction after an error; %s",
4210 pg_log_error(
"client %d aborted: end of script reached without completing the last transaction",
4218 pg_log_error(
"perhaps the backend died while processing");
4220 pg_log_error(
"client %d aborted while receiving the transaction status", st->
id);
4293 argc = command->
argc;
4294 argv = command->
argv;
4303 for (
int i = 1;
i < argc;
i++)
4323 commandFailed(st,
"sleep",
"execution of meta-command failed");
4338 commandFailed(st, argv[0],
"evaluation of meta-command failed");
4344 commandFailed(st,
"set",
"assignment of meta-command failed");
4357 commandFailed(st, argv[0],
"evaluation of meta-command failed");
4380 commandFailed(st, argv[0],
"evaluation of meta-command failed");
4414 commandFailed(st,
"setshell",
"execution of meta-command failed");
4422 commandFailed(st,
"shell",
"execution of meta-command failed");
4434 commandFailed(st,
"startpipeline",
"cannot use pipeline mode with the simple query protocol");
4450 commandFailed(st,
"startpipeline",
"already in pipeline mode");
4455 commandFailed(st,
"startpipeline",
"failed to enter pipeline mode");
4468 commandFailed(st,
"syncpipeline",
"failed to send a pipeline sync");
4482 commandFailed(st,
"endpipeline",
"failed to send a pipeline sync");
4524 return "serialization";
4529 pg_fatal(
"unexpected error status: %d", estatus);
4547 StatsData *agg,
bool skipped,
double latency,
double lag)
4575 double lag_sum = 0.0;
4576 double lag_sum2 = 0.0;
4577 double lag_min = 0.0;
4578 double lag_max = 0.0;
4580 int64 serialization_failures = 0;
4581 int64 deadlock_failures = 0;
4624 serialization_failures,
4643 now / 1000000,
now % 1000000);
4669 double latency = 0.0,
4694 doLog(thread, st, agg, skipped, latency, lag);
4709 for (
i = 0;
i < length;
i++)
4719 fprintf(stderr,
"dropping old tables...\n");
4726 "pgbench_accounts, "
4727 "pgbench_branches, "
4757 "create%s table pgbench_accounts_%d\n"
4758 " partition of pgbench_accounts\n"
4759 " for values from (",
4784 "create%s table pgbench_accounts_%d\n"
4785 " partition of pgbench_accounts\n"
4786 " for values with (modulus %d, remainder %d)",
4825 const char *bigcols;
4826 int declare_fillfactor;
4828 static const struct ddlinfo DDLs[] = {
4831 "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
4832 "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)",
4837 "tid int not null,bid int,tbalance int,filler char(84)",
4838 "tid int not null,bid int,tbalance int,filler char(84)",
4843 "aid int not null,bid int,abalance int,filler char(84)",
4844 "aid bigint not null,bid int,abalance int,filler char(84)",
4849 "bid int not null,bbalance int,filler char(88)",
4850 "bid int not null,bbalance int,filler char(88)",
4857 fprintf(stderr,
"creating tables...\n");
4863 const struct ddlinfo *ddl = &DDLs[
i];
4875 else if (ddl->declare_fillfactor)
4883 char *escape_tablespace;
4906 "pgbench_accounts, "
4907 "pgbench_branches, "
4948 char copy_statement[256];
4949 const char *copy_statement_fmt =
"copy %s from stdin";
4950 int64 total = base *
scale;
4954 int log_interval = 1;
4957 char eol = isatty(fileno(stderr)) ?
'\r' :
'\n';
4967 if (strcmp(table,
"pgbench_accounts") != 0 ||
4969 copy_statement_fmt =
"copy %s from stdin with (freeze on)";
4972 n =
pg_snprintf(copy_statement,
sizeof(copy_statement), copy_statement_fmt, table);
4973 if (n >=
sizeof(copy_statement))
4974 pg_fatal(
"invalid buffer size: must be at least %d characters long", n);
4986 for (k = 0; k < total; k++)
5004 double remaining_sec = ((double) total -
j) * elapsed_sec /
j;
5008 (
int) ((
j * 100) / total),
5009 table, elapsed_sec, remaining_sec, eol);
5015 double remaining_sec = ((double) total -
j) * elapsed_sec /
j;
5022 (
int) ((
j * 100) / total),
5023 table, elapsed_sec, remaining_sec, eol);
5031 if (
chars != 0 && eol !=
'\n')
5035 pg_fatal(
"very last PQputline failed");
5051 fprintf(stderr,
"generating data (client-side)...\n");
5085 fprintf(stderr,
"generating data (server-side)...\n");
5099 "insert into pgbench_branches(bid,bbalance) "
5105 "insert into pgbench_tellers(tid,bid,tbalance) "
5106 "select tid, (tid - 1) / %d + 1, 0 "
5111 "insert into pgbench_accounts(aid,bid,abalance,filler) "
5112 "select aid, (aid - 1) / %d + 1, 0, '' "
5128 fprintf(stderr,
"vacuuming...\n");
5141 static const char *
const DDLINDEXes[] = {
5142 "alter table pgbench_branches add primary key (bid)",
5143 "alter table pgbench_tellers add primary key (tid)",
5144 "alter table pgbench_accounts add primary key (aid)"
5149 fprintf(stderr,
"creating primary keys...\n");
5159 char *escape_tablespace;
5179 static const char *
const DDLKEYs[] = {
5180 "alter table pgbench_tellers add constraint pgbench_tellers_bid_fkey foreign key (bid) references pgbench_branches",
5181 "alter table pgbench_accounts add constraint pgbench_accounts_bid_fkey foreign key (bid) references pgbench_branches",
5182 "alter table pgbench_history add constraint pgbench_history_bid_fkey foreign key (bid) references pgbench_branches",
5183 "alter table pgbench_history add constraint pgbench_history_tid_fkey foreign key (tid) references pgbench_tellers",
5184 "alter table pgbench_history add constraint pgbench_history_aid_fkey foreign key (aid) references pgbench_accounts"
5188 fprintf(stderr,
"creating foreign keys...\n");
5205 if (initialize_steps[0] ==
'\0')
5206 pg_fatal(
"no initialization steps specified");
5208 for (
const char *step = initialize_steps; *step !=
'\0'; step++)
5212 pg_log_error(
"unrecognized initialization step \"%c\"", *step);
5228 double run_time = 0.0;
5234 pg_fatal(
"could not create connection for initialization");
5239 for (step = initialize_steps; *step !=
'\0'; step++)
5251 op =
"create tables";
5255 op =
"client-side generate";
5259 op =
"server-side generate";
5267 op =
"primary keys";
5271 op =
"foreign keys";
5277 pg_log_error(
"unrecognized initialization step \"%c\"", *step);
5293 run_time += elapsed_sec;
5297 fprintf(stderr,
"done in %.2f s (%s).\n", run_time, stats.
data);
5316 res =
PQexec(con,
"select count(*) from pgbench_branches");
5324 pg_log_error_hint(
"Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".",
5331 pg_fatal(
"invalid count(*) from pgbench_branches: \"%s\"",
5337 pg_log_warning(
"scale option ignored, using count from pgbench_branches table (%d)",
5356 "select o.n, p.partstrat, pg_catalog.count(i.inhparent) "
5357 "from pg_catalog.pg_class as c "
5358 "join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) "
5359 "cross join lateral (select pg_catalog.array_position(pg_catalog.current_schemas(true), n.nspname)) as o(n) "
5360 "left join pg_catalog.pg_partitioned_table as p on (p.partrelid = c.oid) "
5361 "left join pg_catalog.pg_inherits as i on (c.oid = i.inhparent) "
5362 "where c.relname = 'pgbench_accounts' and o.n is not null "
5379 pg_log_error(
"no pgbench_accounts table found in search_path");
5380 pg_log_error_hint(
"Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".",
PQdb(con));
5395 if (strcmp(
ps,
"r") == 0)
5397 else if (strcmp(
ps,
"h") == 0)
5402 pg_fatal(
"unexpected partition method: \"%s\"",
ps);
5425 while ((p = strchr(p,
':')) != NULL)
5447 pg_log_error(
"statement has too many arguments (maximum is %d): %s",
5479 const char *line,
const char *command,
5480 const char *msg,
const char *more,
int column)
5489 if (column >= 0 && line == NULL)
5491 if (command != NULL)
5500 fprintf(stderr,
"%s\n", line);
5502 fprintf(stderr,
"%*c error found here\n", column + 1,
'^');
5516 char *p = sql_command;
5521 if (isspace((
unsigned char) *p))
5523 else if (strncmp(p,
"--", 2) == 0)
5525 p = strchr(p,
'\n');
5564 my_command->
argc = 0;
5567 memset(my_command->
argv, 0,
sizeof(my_command->
argv));
5569 my_command->
expr = NULL;
5582 for (
int i = 0;
i < command->
argc;
i++)
5601 static int prepnum = 0;
5607 buffer[strcspn(buffer,
"\n\r")] =
'\0';
5661 my_command->
argc = 0;
5666 offsets[
j] = word_offset;
5684 "missing argument", NULL, -1);
5686 offsets[
j] = word_offset;
5693 my_command->
argv[0]);
5726 "too many arguments", NULL, -1);
5728 offsets[
j] = word_offset;
5742 if (my_command->
argc < 2)
5744 "missing argument", NULL, -1);
5746 if (my_command->
argc > 3)
5748 "too many arguments", NULL,
5749 offsets[3] - start_offset);
5757 if (my_command->
argv[1][0] !=
':')
5759 char *
c = my_command->
argv[1];
5760 bool have_digit =
false;
5763 if (*
c ==
'+' || *
c ==
'-')
5767 if (*
c && isdigit((
unsigned char) *
c))
5771 while (*
c && isdigit((
unsigned char) *
c))
5776 if (my_command->
argc == 2 && have_digit)
5778 my_command->
argv[2] =
c;
5779 offsets[2] = offsets[1] + (
c - my_command->
argv[1]);
5780 my_command->
argc = 3;
5789 "invalid sleep time, must be an integer",
5790 my_command->
argv[1], offsets[1] - start_offset);
5795 if (my_command->
argc == 3)
5801 "unrecognized time unit, must be us, ms or s",
5802 my_command->
argv[2], offsets[2] - start_offset);
5807 if (my_command->
argc < 3)
5809 "missing argument", NULL, -1);
5813 if (my_command->
argc < 2)
5815 "missing command", NULL, -1);
5822 if (my_command->
argc != 1)
5824 "unexpected argument", NULL, -1);
5828 if (my_command->
argc > 2)
5830 "too many arguments", NULL, -1);
5836 "invalid command", NULL, -1);
5847 pg_fatal(
"condition error in script \"%s\" command %d: %s",
5861 for (
i = 0;
ps->commands[
i] != NULL;
i++)
5905 ParseScript(
const char *script,
const char *desc,
int weight)
5915 #define COMMANDS_ALLOC_NUM 128
5952 sr =
psql_scan(sstate, &line_buf, &prompt);
5959 ps.commands[
index++] = command;
5978 "\\gset must follow an SQL command",
5986 "\\gset must follow an SQL command",
5990 if (command->
argc <= 1 || command->
argv[1][0] ==
'\0')
6005 ps.commands[
index++] = command;
6014 if (
index >= alloc_num)
6045 size_t buflen = BUFSIZ;
6054 nread = fread(
buf + used, 1, BUFSIZ,
fd);
6083 else if ((
fd = fopen(
filename,
"r")) == NULL)
6112 fprintf(stderr,
"Available builtin scripts:\n");
6144 pg_log_error(
"ambiguous builtin name: %d builtin scripts found for prefix \"%s\"", found,
name);
6163 int namelen = sep -
option;
6169 strncpy(*script,
option, namelen);
6170 (*script)[namelen] =
'\0';
6174 wtmp = strtol(sep + 1, &badp, 10);
6175 if (errno != 0 || badp == sep + 1 || *badp !=
'\0')
6176 pg_fatal(
"invalid weight specification: %s", sep);
6177 if (wtmp > INT_MAX || wtmp < 0)
6178 pg_fatal(
"weight specification out of range (0 .. %d): %lld",
6179 INT_MAX, (
long long) wtmp);
6196 pg_fatal(
"empty command list for script \"%s\"", script->
desc);
6250 cur.serialization_failures +=
6256 cnt =
cur.cnt - last->
cnt;
6257 total_run = (
now - test_start) / 1000000.0;
6258 tps = 1000000.0 * cnt / run;
6261 latency = 0.001 * (
cur.latency.sum - last->
latency.
sum) / cnt;
6263 stdev = 0.001 * sqrt(sqlat - 1000000.0 * latency * latency);
6264 lag = 0.001 * (
cur.lag.sum - last->
lag.
sum) / cnt;
6268 latency = sqlat = stdev = lag = 0;
6275 snprintf(tbuf,
sizeof(tbuf),
"%.3f s",
6281 snprintf(tbuf,
sizeof(tbuf),
"%.1f s", total_run);
6285 "progress: %s, %.1f tps, lat %.3f ms stddev %.3f, " INT64_FORMAT " failed",
6286 tbuf, tps, latency, stdev, failures);
6290 fprintf(stderr,
", lag %.3f ms", lag);
6312 double latency = ss->
sum / ss->
count;
6313 double stddev = sqrt(ss->
sum2 / ss->
count - latency * latency);
6315 printf(
"%s average = %.3f ms\n", prefix, 0.001 * latency);
6316 printf(
"%s stddev = %.3f ms\n", prefix, 0.001 * stddev);
6325 int client_ver = PG_VERSION_NUM;
6327 if (server_ver != client_ver)
6338 sverbuf,
sizeof(sverbuf));
6342 printf(
_(
"%s (%s, server %s)\n"),
6347 printf(
"%s (%s)\n",
"pgbench", PG_VERSION);
6361 int64 total_cnt = total->
cnt + total->
skipped + failures;
6363 double tps = total->
cnt / bench_duration;
6366 printf(
"transaction type: %s\n",
6371 printf(
"partition method: %s\npartitions: %d\n",
6382 printf(
"number of transactions per client: %d\n",
nxacts);
6394 failures, 100.0 * failures / total_cnt);
6425 (total->
cnt > 0) ? 100.0 * latency_late / total->
cnt : 0.0);
6432 printf(
"latency average = %.3f ms%s\n",
6433 0.001 * total_duration *
nclients / total_cnt,
6434 failures > 0 ?
" (including failures)" :
"");
6445 printf(
"rate limit schedule lag: avg %.3f (max %.3f) ms\n",
6460 printf(
"average connection time = %.3f ms\n", 0.001 * conn_total_duration / (total->
cnt + failures));
6461 printf(
"tps = %f (including reconnection times)\n", tps);
6465 printf(
"initial connection time = %.3f ms\n", 0.001 * conn_elapsed_duration);
6466 printf(
"tps = %f (without initial connection time)\n", tps);
6480 int64 script_total_cnt =
6481 sstats->
cnt + sstats->
skipped + script_failures;
6483 printf(
"SQL script %d: %s\n"
6484 " - weight: %d (targets %.1f%% of total)\n"
6485 " - " INT64_FORMAT " transactions (%.1f%% of total, tps = %f)\n",
6490 100.0 * sstats->
cnt / total->
cnt,
6491 sstats->
cnt / bench_duration);
6495 100.0 * script_failures / script_total_cnt);
6514 100.0 * sstats->
retried / script_total_cnt);
6522 100.0 * sstats->
skipped / script_total_cnt);
6535 printf(
"%sstatement latencies in milliseconds%s:\n",
6539 ", failures and retries"));
6548 printf(
" %11.3f %10" INT64_MODIFIER
"d %s\n",
6549 (cstats->
count > 0) ?
6550 1000.0 * cstats->
sum / cstats->
count : 0.0,
6551 (*commands)->failures,
6552 (*commands)->first_line);
6554 printf(
" %11.3f %10" INT64_MODIFIER
"d %10" INT64_MODIFIER
"d %s\n",
6555 (cstats->
count > 0) ?
6556 1000.0 * cstats->
sum / cstats->
count : 0.0,
6557 (*commands)->failures,
6558 (*commands)->retries,
6559 (*commands)->first_line);
6575 if (seed == NULL || strcmp(seed,
"time") == 0)
6580 else if (strcmp(seed,
"rand") == 0)
6592 unsigned long ulseed;
6596 if (sscanf(seed,
"%lu%c", &ulseed, &garbage) != 1)
6598 pg_log_error(
"unrecognized random seed option \"%s\"", seed);
6602 iseed = (uint64) ulseed;
6606 pg_log_info(
"setting random seed to %llu", (
unsigned long long) iseed);
6617 main(
int argc,
char **argv)
6619 static struct option long_options[] = {
6670 bool is_init_mode =
false;
6671 char *initialize_steps = NULL;
6672 bool foreign_keys =
false;
6673 bool is_no_vacuum =
false;
6674 bool do_vacuum_accounts =
false;
6676 bool scale_given =
false;
6678 bool benchmarking_option_set =
false;
6679 bool initialization_option_set =
false;
6680 bool internal_script_used =
false;
6688 conn_total_duration;
6690 int64 latency_late = 0;
6697 #ifdef HAVE_GETRLIMIT
6719 if (strcmp(argv[1],
"--help") == 0 || strcmp(argv[1],
"-?") == 0)
6724 if (strcmp(argv[1],
"--version") == 0 || strcmp(argv[1],
"-V") == 0)
6726 puts(
"pgbench (PostgreSQL) " PG_VERSION);
6735 pg_fatal(
"error while setting random seed from PGBENCH_RANDOM_SEED environment variable");
6737 while ((
c =
getopt_long(argc, argv,
"b:c:Cd:D:f:F:h:iI:j:lL:M:nNp:P:qrR:s:St:T:U:v", long_options, &optindex)) != -1)
6744 if (strcmp(
optarg,
"list") == 0)
6751 benchmarking_option_set =
true;
6752 internal_script_used =
true;
6755 benchmarking_option_set =
true;
6761 #ifdef HAVE_GETRLIMIT
6762 if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
6766 pg_log_error(
"need at least %d open files, but system limit is %ld",
6767 nclients + 3, (
long) rlim.rlim_cur);
6768 pg_log_error_hint(
"Reduce number of clients, or use limit/ulimit to increase the system limit.");
6774 benchmarking_option_set =
true;
6784 benchmarking_option_set =
true;
6786 if ((p = strchr(
optarg,
'=')) == NULL || p ==
optarg || *(p + 1) ==
'\0')
6797 benchmarking_option_set =
true;
6800 initialization_option_set =
true;
6809 is_init_mode =
true;
6815 initialization_option_set =
true;
6818 benchmarking_option_set =
true;
6826 benchmarking_option_set =
true;
6831 double limit_ms = atof(
optarg);
6833 if (limit_ms <= 0.0)
6835 benchmarking_option_set =
true;
6840 benchmarking_option_set =
true;
6848 is_no_vacuum =
true;
6852 benchmarking_option_set =
true;
6853 internal_script_used =
true;
6859 benchmarking_option_set =
true;
6865 initialization_option_set =
true;
6869 benchmarking_option_set =
true;
6875 double throttle_value = atof(
optarg);
6877 benchmarking_option_set =
true;
6879 if (throttle_value <= 0.0)
6893 benchmarking_option_set =
true;
6894 internal_script_used =
true;
6897 benchmarking_option_set =
true;
6903 benchmarking_option_set =
true;
6912 benchmarking_option_set =
true;
6913 do_vacuum_accounts =
true;
6916 initialization_option_set =
true;
6920 initialization_option_set =
true;
6924 initialization_option_set =
true;
6928 benchmarking_option_set =
true;
6930 if (sample_rate <= 0.0 || sample_rate > 1.0)
6934 benchmarking_option_set =
true;
6941 benchmarking_option_set =
true;
6944 benchmarking_option_set =
true;
6948 initialization_option_set =
true;
6949 foreign_keys =
true;
6952 benchmarking_option_set =
true;
6954 pg_fatal(
"error while setting random seed from --random-seed option");
6965 initialization_option_set =
true;
6971 initialization_option_set =
true;
6977 pg_fatal(
"invalid partition method, expecting \"range\" or \"hash\", got: \"%s\"",
6981 benchmarking_option_set =
true;
6988 if (max_tries_arg < 0)
6991 benchmarking_option_set =
true;
6996 benchmarking_option_set =
true;
7000 benchmarking_option_set =
true;
7017 benchmarking_option_set =
true;
7018 internal_script_used =
true;
7026 for (
int j = 0; commands[
j] != NULL;
j++)
7035 pg_fatal(
"total script weight must not be zero");
7062 if ((env = getenv(
"PGDATABASE")) != NULL && *env !=
'\0')
7064 else if ((env = getenv(
"PGUSER")) != NULL && *env !=
'\0')
7073 pg_log_error(
"too many command-line arguments (first is \"%s\")",
7081 if (benchmarking_option_set)
7082 pg_fatal(
"some of the specified options cannot be used in initialization (-i) mode");
7085 pg_fatal(
"--partition-method requires greater than zero --partitions");
7091 if (initialize_steps == NULL)
7099 while ((p = strchr(initialize_steps,
'v')) != NULL)
7106 if (strchr(initialize_steps,
'f') == NULL)
7108 initialize_steps = (
char *)
7110 strlen(initialize_steps) + 2);
7111 strcat(initialize_steps,
"f");
7120 if (initialization_option_set)
7121 pg_fatal(
"some of the specified options cannot be used in benchmarking mode");
7125 pg_fatal(
"specify either a number of transactions (-t) or a duration (-T), not both");
7133 pg_fatal(
"log sampling (--sampling-rate) is allowed only when logging transactions (-l)");
7137 pg_fatal(
"log sampling (--sampling-rate) and aggregation (--aggregate-interval) cannot be used at the same time");
7140 pg_fatal(
"log aggregation is allowed only when actually logging transactions");
7143 pg_fatal(
"log file prefix (--log-prefix) is allowed only when logging transactions (-l)");
7152 pg_fatal(
"--progress-timestamp is allowed only under --progress");
7157 pg_fatal(
"an unlimited number of transaction tries can only be used with --latency-limit or a duration (-T)");
7177 for (
j = 0;
j <
state[0].variables.nvars;
j++)
7207 pg_fatal(
"could not create connection for setup");
7212 pg_log_debug(
"pghost: %s pgport: %s nclients: %d %s: %d dbName: %s",
7214 duration <= 0 ?
"nxacts" :
"duration",
7217 if (internal_script_used)
7266 fprintf(stderr,
"starting vacuum...");
7272 if (do_vacuum_accounts)
7274 fprintf(stderr,
"starting vacuum pgbench_accounts...");
7300 nclients_dealt += thread->
nstate;
7315 pg_fatal(
"could not initialize barrier: %m");
7326 pg_fatal(
"could not create thread: %m");
7339 conn_total_duration = 0;
7348 for (
int j = 0;
j < thread->
nstate;
j++)
7365 if (bench_start == 0 || thread->
bench_start < bench_start)
7389 pg_log_error(
"Run was aborted; the above results are incomplete.");
7400 int nstate = thread->
nstate;
7401 int remains = nstate;
7415 if (thread->
tid == 0)
7420 thread->
logfile = fopen(logpath,
"w");
7423 pg_fatal(
"could not open logfile \"%s\": %m", logpath);
7427 for (
int i = 0;
i < nstate;
i++)
7436 last_report = thread_start;
7437 next_report = last_report + (int64) 1000000 *
progress;
7443 for (
int i = 0;
i < nstate;
i++)
7448 pg_fatal(
"could not create connection for client %d",
7485 for (
int i = 0;
i < nstate;
i++)
7500 if (min_usec > this_usec)
7501 min_usec = this_usec;
7537 if (
now >= next_report)
7539 else if ((next_report -
now) < min_usec)
7540 min_usec = next_report -
now;
7589 for (
int i = 0;
i < nstate;
i++)
7638 if (now2 >= next_report)
7647 &last, &last_report);
7655 next_report += (int64) 1000000 *
progress;
7656 }
while (now2 >= next_report);
7667 for (
int i = 0;
i < nstate;
i++)
7671 pg_log_error(
"Run was aborted due to an error in thread %d",
7697 if (st->
con != NULL)
7725 static VOID CALLBACK
7726 win32_timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
7738 queue = CreateTimerQueue();
7739 if (seconds > ((DWORD) -1) / 1000 ||
7740 !CreateTimerQueueTimer(&timer, queue,
7741 win32_timer_callback, NULL, seconds * 1000, 0,
7742 WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE))
7784 #ifdef POLL_USING_PPOLL
7792 sizeof(
struct pollfd) * count);
7815 sa->pollfds[
idx].events = POLLIN;
7816 sa->pollfds[
idx].revents = 0;
7825 struct timespec timeout;
7827 timeout.tv_sec = usecs / 1000000;
7828 timeout.tv_nsec = (usecs % 1000000) * 1000;
7829 return ppoll(
sa->pollfds,
sa->curfds, &timeout, NULL);
7833 return ppoll(
sa->pollfds,
sa->curfds, NULL, NULL);
7848 if (
sa->curfds == 0)
7852 return (
sa->pollfds[
idx].revents & POLLIN) != 0;
7857 #ifdef POLL_USING_SELECT
7883 if (
sa->fds.fd_count + 1 >= FD_SETSIZE)
7885 pg_log_error(
"too many concurrent database clients for this platform: %d",
7886 sa->fds.fd_count + 1);
7890 if (fd < 0 || fd >= FD_SETSIZE)
7892 pg_log_error(
"socket file descriptor out of range for select(): %d",
7898 FD_SET(
fd, &
sa->fds);
7908 struct timeval timeout;
7910 timeout.tv_sec = usecs / 1000000;
7911 timeout.tv_usec = usecs % 1000000;
7912 return select(
sa->maxfd + 1, &
sa->fds, NULL, NULL, &timeout);
7916 return select(
sa->maxfd + 1, &
sa->fds, NULL, NULL, NULL);
7923 return (FD_ISSET(
fd, &
sa->fds) != 0);
Datum idx(PG_FUNCTION_ARGS)
Datum now(PG_FUNCTION_ARGS)
static Datum values[MAXATTR]
#define IS_HIGHBIT_SET(ch)
#define Assert(condition)
#define FLEXIBLE_ARRAY_MEMBER
#define FLOAT8_FITS_IN_INT64(num)
volatile sig_atomic_t CancelRequested
void ResetCancelConn(void)
void SetCancelConn(PGconn *conn)
void setup_cancel_handler(void(*query_cancel_callback)(void))
ifState conditional_stack_peek(ConditionalStack cstack)
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
ConditionalStack conditional_stack_create(void)
bool conditional_stack_pop(ConditionalStack cstack)
void conditional_stack_destroy(ConditionalStack cstack)
bool conditional_active(ConditionalStack cstack)
void conditional_stack_reset(ConditionalStack cstack)
bool conditional_stack_poke(ConditionalStack cstack, ifState new_state)
bool conditional_stack_empty(ConditionalStack cstack)
static void PGresult * res
const char * PQparameterStatus(const PGconn *conn, const char *paramName)
int PQserverVersion(const PGconn *conn)
char * PQhost(const PGconn *conn)
PGconn * PQconnectdbParams(const char *const *keywords, const char *const *values, int expand_dbname)
char * PQdb(const PGconn *conn)
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
int PQconnectionNeedsPassword(const PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
ConnStatusType PQstatus(const PGconn *conn)
void PQfinish(PGconn *conn)
char * PQport(const PGconn *conn)
PGpipelineStatus PQpipelineStatus(const PGconn *conn)
int PQsocket(const PGconn *conn)
int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
void PQfreemem(void *ptr)
PGresult * PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
int PQexitPipelineMode(PGconn *conn)
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
int PQenterPipelineMode(PGconn *conn)
ExecStatusType PQresultStatus(const PGresult *res)
int PQendcopy(PGconn *conn)
int PQsendPipelineSync(PGconn *conn)
int PQntuples(const PGresult *res)
int PQputline(PGconn *conn, const char *string)
char * PQfname(const PGresult *res, int field_num)
PGresult * PQexec(PGconn *conn, const char *query)
int PQconsumeInput(PGconn *conn)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
int PQsendQuery(PGconn *conn, const char *query)
int PQpipelineSync(PGconn *conn)
int PQisBusy(PGconn *conn)
int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
char * PQresultErrorField(const PGresult *res, int fieldcode)
int PQnfields(const PGresult *res)
PGresult * PQgetResult(PGconn *conn)
void * pg_realloc(void *ptr, size_t size)
void * pg_malloc0(size_t size)
char * pg_strdup(const char *in)
void * pg_malloc(size_t size)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
static const FormData_pg_attribute a1
static const FormData_pg_attribute a2
#define INSTR_TIME_SET_CURRENT(t)
#define INSTR_TIME_GET_MICROSEC(t)
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
static void const char fflush(stdout)
void pg_logging_increase_verbosity(void)
void pg_logging_init(const char *argv0)
enum pg_log_level __pg_log_level
#define pg_log_error(...)
#define pg_log_error_hint(...)
#define pg_log_error_detail(...)
#define pg_log_debug(...)
bool option_parse_int(const char *optarg, const char *optname, int min_range, int max_range, int *result)
static int pg_leftmost_one_pos64(uint64 word)
static int server_version
PGDLLIMPORT char * optarg
double pg_prng_double(pg_prng_state *state)
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
uint64 pg_prng_uint64(pg_prng_state *state)
void pg_prng_seed(pg_prng_state *state, uint64 seed)
double pg_prng_double_normal(pg_prng_state *state)
static rewind_source * source
void syntax_error(const char *source, int lineno, const char *line, const char *command, const char *msg, const char *more, int column)
static Variable * lookupVariable(Variables *variables, char *name)
static QueryMode querymode
static void printResults(StatsData *total, pg_time_usec_t total_duration, pg_time_usec_t conn_total_duration, pg_time_usec_t conn_elapsed_duration, int64 latency_late)
static bool putVariableInt(Variables *variables, const char *context, char *name, int64 value)
static char * read_file_contents(FILE *fd)
static pg_time_usec_t pg_time_now(void)
bool strtodouble(const char *str, bool errorOK, double *dv)
static void accumStats(StatsData *stats, bool skipped, double lat, double lag, EStatus estatus, int64 tries)
#define THREAD_FUNC_RETURN_TYPE
static void initCreatePKeys(PGconn *con)
static void GetTableInfo(PGconn *con, bool scale_given)
static void printVerboseErrorMessages(CState *st, pg_time_usec_t *now, bool is_retry)
static void initRandomState(pg_prng_state *state)
static bool isLazyFunc(PgBenchFunction func)
static int64 getZipfianRand(pg_prng_state *state, int64 min, int64 max, double s)
#define THREAD_BARRIER_WAIT(barrier)
static const BuiltinScript * findBuiltin(const char *name)
static void setIntValue(PgBenchValue *pv, int64 ival)
static char * getVariable(Variables *variables, char *name)
static THREAD_FUNC_RETURN_TYPE THREAD_FUNC_CC threadRun(void *arg)
#define SHELL_COMMAND_SIZE
static void setalarm(int seconds)
struct BuiltinScript BuiltinScript
static void initTeller(PQExpBufferData *sql, int64 curr)
static TStatus getTransactionStatus(PGconn *con)
static bool exit_on_abort
static bool coerceToInt(PgBenchValue *pval, int64 *ival)
static void setNullValue(PgBenchValue *pv)
#define SOCKET_WAIT_METHOD
static bool doRetry(CState *st, pg_time_usec_t *now)
static bool evalLazyFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
#define ERRCODE_T_R_DEADLOCK_DETECTED
static int64 getExponentialRand(pg_prng_state *state, int64 min, int64 max, double parameter)
static void free_socket_set(socket_set *sa)
static void CheckConditional(const ParsedScript *ps)
static bool sendCommand(CState *st, Command *command)
static void doLog(TState *thread, CState *st, StatsData *agg, bool skipped, double latency, double lag)
#define COMMANDS_ALLOC_NUM
#define ERRCODE_T_R_SERIALIZATION_FAILURE
static void prepareCommandsInPipeline(CState *st)
int main(int argc, char **argv)
static Variable * lookupCreateVariable(Variables *variables, const char *context, char *name)
static bool putVariable(Variables *variables, const char *context, char *name, const char *value)
static void finishCon(CState *st)
static int compareVariableNames(const void *v1, const void *v2)
static const char * getResultString(bool skipped, EStatus estatus)
static void printVersion(PGconn *con)
static void initBranch(PQExpBufferData *sql, int64 curr)
struct socket_set socket_set
static bool evaluateExpr(CState *st, PgBenchExpr *expr, PgBenchValue *retval)
static bool parseQuery(Command *cmd)
static void initStats(StatsData *sd, pg_time_usec_t start)
static pg_prng_state base_random_sequence
static void setDoubleValue(PgBenchValue *pv, double dval)
static void checkInitSteps(const char *initialize_steps)
static void createPartitions(PGconn *con)
static void initDropTables(PGconn *con)
static void clear_socket_set(socket_set *sa)
static void free_command(Command *command)
static void postprocess_sql_command(Command *my_command)
static const char *const QUERYMODE[]
@ CSTATE_WAIT_ROLLBACK_RESULT
@ CSTATE_PREPARE_THROTTLE
static void handle_sig_alarm(SIGNAL_ARGS)
static bool evalFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
static char * valueTypeName(PgBenchValue *pval)
static bool runShellCommand(Variables *variables, char *variable, char **argv, int argc)
#define MIN_ZIPFIAN_PARAM
#define PARAMS_ARRAY_SIZE
void(* initRowMethod)(PQExpBufferData *sql, int64 curr)
static void initGenerateDataServerSide(PGconn *con)
static bool makeVariableValue(Variable *var)
static Command * process_backslash_command(PsqlScanState sstate, const char *source)
static MetaCommand getMetaCommand(const char *cmd)
static void mergeSimpleStats(SimpleStats *acc, SimpleStats *ss)
#define THREAD_JOIN(handle)
static void printSimpleStats(const char *prefix, SimpleStats *ss)
#define ERRCODE_UNDEFINED_TABLE
static void listAvailableScripts(void)
#define PG_TIME_GET_DOUBLE(t)
static bool set_random_seed(const char *seed)
static void add_socket_to_set(socket_set *sa, int fd, int idx)
static int discardUntilSync(CState *st)
static EStatus getSQLErrorStatus(const char *sqlState)
static int64 total_weight
#define THREAD_FUNC_RETURN
static ConnectionStateEnum executeMetaCommand(CState *st, pg_time_usec_t *now)
#define VARIABLES_ALLOC_MARGIN
static void initCreateFKeys(PGconn *con)
static const BuiltinScript builtin_script[]
static int64 getFailures(const StatsData *stats)
static ParsedScript sql_script[MAX_SCRIPTS]
static bool canRetryError(EStatus estatus)
static void runInitSteps(const char *initialize_steps)
static int64 permute(const int64 val, const int64 isize, const int64 seed)
static void commandFailed(CState *st, const char *cmd, const char *message)
static int chooseScript(TState *thread)
static bool evalStandardFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
static void addScript(const ParsedScript *script)
static void setBoolValue(PgBenchValue *pv, bool bval)
static void initTruncateTables(PGconn *con)
bool strtoint64(const char *str, bool errorOK, int64 *result)
@ ESTATUS_META_COMMAND_ERROR
@ ESTATUS_OTHER_SQL_ERROR
@ ESTATUS_SERIALIZATION_ERROR
struct StatsData StatsData
static int64 computeIterativeZipfian(pg_prng_state *state, int64 n, double s)
static void advanceConnectionState(TState *thread, CState *st, StatsData *agg)
static void ConditionError(const char *desc, int cmdn, const char *msg)
static bool evaluateSleep(Variables *variables, int argc, char **argv, int *usecs)
static void process_builtin(const BuiltinScript *bi, int weight)
static int parseScriptWeight(const char *option, char **script)
struct SimpleStats SimpleStats
struct ParsedScript ParsedScript
static void initVacuum(PGconn *con)
static bool putVariableValue(Variables *variables, const char *context, char *name, const PgBenchValue *value)
static void initAccount(PQExpBufferData *sql, int64 curr)
static void commandError(CState *st, const char *message)
static char * assignVariables(Variables *variables, char *sql)
static void tryExecuteStatement(PGconn *con, const char *sql)
static bool valid_variable_name(const char *name)
static partition_method_t partition_method
static int64 getrand(pg_prng_state *state, int64 min, int64 max)
static const char *const PARTITION_METHOD[]
static void getQueryParams(Variables *variables, const Command *command, const char **params)
volatile sig_atomic_t timer_exceeded
static char * skip_sql_comments(char *sql_command)
static void enlargeVariables(Variables *variables, int needed)
static THREAD_BARRIER_T barrier
static void printProgressReport(TState *threads, int64 test_start, pg_time_usec_t now, StatsData *last, int64 *last_report)
static void processXactStats(TState *thread, CState *st, pg_time_usec_t *now, bool skipped, StatsData *agg)
static void initSimpleStats(SimpleStats *ss)
static int64 getHashMurmur2(int64 val, uint64 seed)
static void process_file(const char *filename, int weight)
static const PsqlScanCallbacks pgbench_callbacks
static void ParseScript(const char *script, const char *desc, int weight)
static void prepareCommand(CState *st, int command_num)
#define THREAD_BARRIER_INIT(barrier, n)
static bool socket_has_input(socket_set *sa, int fd, int idx)
static bool valueTruth(PgBenchValue *pval)
static bool is_an_int(const char *str)
static void pg_time_now_lazy(pg_time_usec_t *now)
static int64 getGaussianRand(pg_prng_state *state, int64 min, int64 max, double parameter)
static void addToSimpleStats(SimpleStats *ss, double val)
static void initPopulateTable(PGconn *con, const char *table, int64 base, initRowMethod init_row)
static void allocCStatePrepared(CState *st)
static void disconnect_all(CState *state, int length)
static Command * create_sql_command(PQExpBuffer buf, const char *source)
#define DEFAULT_INIT_STEPS
static void initCreateTables(PGconn *con)
static bool verbose_errors
#define MIN_GAUSSIAN_PARAM
#define SCALE_32BIT_THRESHOLD
static int64 getPoissonRand(pg_prng_state *state, double center)
static int wait_on_socket_set(socket_set *sa, int64 usecs)
static void executeStatement(PGconn *con, const char *sql)
#define THREAD_CREATE(handle, function, arg)
static int64 getHashFnv1a(int64 val, uint64 seed)
static char * parseVariable(const char *sql, int *eaten)
static bool coerceToDouble(PgBenchValue *pval, double *dval)
static socket_set * alloc_socket_set(int count)
static PGconn * doConnect(void)
static void initGenerateDataClientSide(PGconn *con)
static bool readCommandResponse(CState *st, MetaCommand meta, char *varprefix)
pg_time_usec_t epoch_shift
static char * replaceVariable(char **sql, char *param, int len, char *value)
#define MAX_ZIPFIAN_PARAM
static bool coerceToBool(PgBenchValue *pval, bool *bval)
#define THREAD_BARRIER_DESTROY(barrier)
int expr_scanner_offset(PsqlScanState state)
@ PGBENCH_RANDOM_EXPONENTIAL
@ PGBENCH_RANDOM_GAUSSIAN
bool expr_lex_one_word(PsqlScanState state, PQExpBuffer word_buf, int *offset)
int expr_yyparse(yyscan_t yyscanner)
int expr_scanner_get_lineno(PsqlScanState state, int offset)
PgBenchExpr * expr_parse_result
void expr_scanner_finish(yyscan_t yyscanner)
yyscan_t expr_scanner_init(PsqlScanState state, const char *source, int lineno, int start_offset, const char *command)
char * expr_scanner_get_substring(PsqlScanState state, int start_offset, int end_offset, bool chomp)
#define pg_log_warning(...)
static core_yyscan_t yyscanner
int int pg_snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
bool pg_strong_random(void *buf, size_t len)
int pg_strcasecmp(const char *s1, const char *s2)
const char * get_progname(const char *argv0)
pqsigfunc pqsignal(int signo, pqsigfunc func)
#define qsort(a, b, c, d)
size_t strlcpy(char *dst, const char *src, size_t siz)
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
PQExpBuffer createPQExpBuffer(void)
void initPQExpBuffer(PQExpBuffer str)
void resetPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
static int fd(const char *x, int i)
char * psprintf(const char *fmt,...)
enum _promptStatus promptStatus_t
void psql_scan_destroy(PsqlScanState state)
PsqlScanResult psql_scan(PsqlScanState state, PQExpBuffer query_buf, promptStatus_t *prompt)
PsqlScanState psql_scan_create(const PsqlScanCallbacks *callbacks)
void psql_scan_setup(PsqlScanState state, const char *line, int line_len, int encoding, bool std_strings)
void psql_scan_finish(PsqlScanState state)
void pg_usleep(long microsec)
static pg_noinline void Size size
char * simple_prompt(const char *prompt, bool echo)
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
pg_time_usec_t txn_scheduled
pg_time_usec_t stmt_begin
pg_time_usec_t sleep_until
pg_prng_state random_state
ConnectionStateEnum state
struct PgBenchExpr::@37::@38 variable
union PgBenchValue::@36 u
int64 serialization_failures
pg_time_usec_t start_time
pg_time_usec_t create_time
pg_prng_state ts_throttle_rs
pg_time_usec_t conn_duration
pg_prng_state ts_choose_rs
pg_time_usec_t bench_start
pg_prng_state ts_sample_rs
pg_time_usec_t started_time
const char * get_user_name_or_exit(const char *progname)
#define select(n, r, w, e, timeout)
int gettimeofday(struct timeval *tp, void *tzp)
static char chars[TZ_MAX_CHARS]