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 " -d, --debug print debugging output\n"
937 " -h, --host=HOSTNAME database server host or socket directory\n"
938 " -p, --port=PORT database server port number\n"
939 " -U, --username=USERNAME connect as specified database user\n"
940 " -V, --version output version information, then exit\n"
941 " -?, --help show this help, then exit\n"
943 "Report bugs to <%s>.\n"
944 "%s home page: <%s>\n",
952 const char *ptr =
str;
955 while (*ptr && isspace((
unsigned char) *ptr))
959 if (*ptr ==
'+' || *ptr ==
'-')
963 if (*ptr && !isdigit((
unsigned char) *ptr))
967 while (*ptr && isdigit((
unsigned char) *ptr))
989 const char *ptr =
str;
1002 while (*ptr && isspace((
unsigned char) *ptr))
1011 else if (*ptr ==
'+')
1015 if (
unlikely(!isdigit((
unsigned char) *ptr)))
1016 goto invalid_syntax;
1019 while (*ptr && isdigit((
unsigned char) *ptr))
1021 int8 digit = (*ptr++ -
'0');
1029 while (*ptr !=
'\0' && isspace((
unsigned char) *ptr))
1033 goto invalid_syntax;
1063 *dv = strtod(
str, &end);
1121 cut = exp(-parameter);
1128 Assert((1.0 - cut) != 0.0);
1129 rand = -log(cut + (1.0 - cut) * uniform) / parameter;
1131 return min + (int64) ((max - min + 1) * rand);
1161 while (stdev < -parameter || stdev >= parameter);
1164 rand = (stdev + parameter) / (parameter * 2.0);
1167 return min + (int64) ((max - min + 1) * rand);
1189 return (int64) (-log(uniform) * center + 0.5);
1202 double b = pow(2.0, s - 1.0);
1218 x = floor(pow(u, -1.0 / (s - 1.0)));
1220 t = pow(1.0 + 1.0 /
x, s - 1.0);
1222 if (v *
x * (t - 1.0) / (
b - 1.0) <= t /
b &&
x <= n)
1232 int64 n = max - min + 1;
1250 for (
i = 0;
i < 8; ++
i)
1255 result = result ^ octet;
1272 uint64 k = (uint64)
val;
1285 return (int64) result;
1302 permute(
const int64
val,
const int64 isize,
const int64 seed)
1319 size = (uint64) isize;
1324 mask = (((uint64) 1) << masklen) - 1;
1355 for (
i = 0;
i < 6;
i++)
1366 v = ((v * m) ^ r) & mask;
1367 v = ((v << 1) & mask) | (v >> (masklen - 1));
1376 t = ((t * m) ^ r) & mask;
1377 t = ((t << 1) & mask) | (t >> (masklen - 1));
1404 if (ss->
count == 0 || val < ss->min)
1467 stats->
retries += (tries - 1);
1493 pg_fatal(
"unexpected error status: %d", estatus);
1542 #define PARAMS_ARRAY_SIZE 7
1547 keywords[0] =
"host";
1549 keywords[1] =
"port";
1551 keywords[2] =
"user";
1553 keywords[3] =
"password";
1555 keywords[4] =
"dbname";
1557 keywords[5] =
"fallback_application_name";
1608 if (variables->
nvars <= 0)
1633 char stringform[64];
1645 snprintf(stringform,
sizeof(stringform),
"NULL");
1647 snprintf(stringform,
sizeof(stringform),
1650 snprintf(stringform,
sizeof(stringform),
1653 snprintf(stringform,
sizeof(stringform),
1670 slen = strlen(var->
svalue);
1714 pg_log_error(
"malformed variable \"%s\" value: \"%s\"",
1739 const unsigned char *ptr = (
const unsigned char *)
name;
1747 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1757 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1758 "_0123456789", *ptr) != NULL)
1775 needed += variables->
nvars;
1811 var = &(variables->
vars[variables->
nvars]);
1895 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1896 "_", sql[
i]) != NULL)
1902 strchr(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1903 "_0123456789", sql[
i]) != NULL)
1907 memcpy(
name, &sql[1],
i - 1);
1917 int valueln = strlen(
value);
1921 size_t offset = param - *sql;
1924 param = *sql + offset;
1928 memmove(param + valueln, param +
len, strlen(param +
len) + 1);
1929 memcpy(param,
value, valueln);
1931 return param + valueln;
1942 while ((p = strchr(p,
':')) != NULL)
1972 const char **params)
1976 for (
i = 0;
i < command->
argc - 1;
i++)
2007 *bval = pval->
u.
bval;
2030 return pval->
u.
bval;
2032 return pval->
u.
ival != 0;
2034 return pval->
u.
dval != 0.0;
2048 *ival = pval->
u.
ival;
2053 double dval = rint(pval->
u.
dval);
2060 *ival = (int64) dval;
2076 *dval = pval->
u.
dval;
2081 *dval = (double) pval->
u.
ival;
2226 if (
args->next == NULL)
2241 #define MAX_FARGS 16
2255 bool has_null =
false;
2263 for (nargs = 0; nargs <
MAX_FARGS && l != NULL; nargs++, l = l->
next)
2511 double d = varg->
u.
dval;
2526 fprintf(stderr,
"debug(script=%d,command=%d): ",
2532 fprintf(stderr,
"boolean %s\n", varg->
u.
bval ?
"true" :
"false");
2536 fprintf(stderr,
"double %.*g\n", DBL_DIG, varg->
u.
dval);
2595 for (
i = 0;
i < nargs;
i++)
2609 for (
i = 1;
i < nargs;
i++)
2616 extremum =
Min(extremum, dval);
2618 extremum =
Max(extremum, dval);
2628 for (
i = 1;
i < nargs;
i++)
2635 extremum =
Min(extremum, ival);
2637 extremum =
Max(extremum, ival);
2692 pg_log_error(
"gaussian parameter must be at least %f (not %f)",
2699 imin, imax, param));
2705 pg_log_error(
"zipfian parameter must be in range [%.3f, %.0f] (not %f)",
2717 pg_log_error(
"exponential parameter must be greater than zero (not %f)",
2724 imin, imax, param));
2802 pg_log_error(
"permute size parameter must be greater than zero");
2838 switch (expr->
etype)
2859 *retval = var->
value;
2871 pg_fatal(
"unexpected enode type in evaluation: %d", expr->
etype);
2939 for (
i = 0;
i < argc;
i++)
2944 if (argv[
i][0] !=
':')
2948 else if (argv[
i][1] ==
':')
2954 pg_log_error(
"%s: undefined variable \"%s\"", argv[0], argv[
i]);
2958 arglen = strlen(
arg);
2961 pg_log_error(
"%s: shell command is too long", argv[0]);
2966 command[
len++] =
' ';
2967 memcpy(command +
len,
arg, arglen);
2971 command[
len] =
'\0';
2978 if (system(command))
2981 pg_log_error(
"%s: could not launch shell command", argv[0]);
2988 if ((fp = popen(command,
"r")) == NULL)
2990 pg_log_error(
"%s: could not launch shell command", argv[0]);
2993 if (fgets(
res,
sizeof(
res), fp) == NULL)
2996 pg_log_error(
"%s: could not read result of shell command", argv[0]);
3002 pg_log_error(
"%s: could not run shell command: %m", argv[0]);
3007 retval = (int) strtol(
res, &endptr, 10);
3008 while (*endptr !=
'\0' && isspace((
unsigned char) *endptr))
3010 if (*
res ==
'\0' || *endptr !=
'\0')
3012 pg_log_error(
"%s: shell command must return an integer (not \"%s\")", argv[0],
res);
3018 pg_log_debug(
"%s: shell parameter name: \"%s\", value: \"%s\"", argv[0], argv[1],
res);
3029 pg_log_error(
"client %d aborted in command %d (%s) of script %d; %s",
3040 pg_log_info(
"client %d got an error in command %d (SQL) of script %d; %s",
3078 for (numcmds = 0; script->
commands[numcmds] != NULL; numcmds++)
3105 command->
argv[0], command->
argc - 1, NULL);
3140 for (
j = st->
command + 1; commands[
j] != NULL;
j++)
3171 const char *sql = command->
argv[0];
3178 NULL, params, NULL, NULL, 0);
3189 params, NULL, NULL, 0);
3209 if (sqlState != NULL)
3262 is_last = (next_res == NULL);
3270 pg_log_error(
"client %d script %d command %d query %d: expected one row, got %d",
3285 pg_log_error(
"client %d script %d command %d query %d: expected one row, got %d",
3290 else if (meta ==
META_ASET && ntuples <= 0)
3302 if (*varprefix !=
'\0')
3303 varname =
psprintf(
"%s%s", varprefix, varname);
3310 pg_log_error(
"client %d script %d command %d query %d: error storing into variable %s",
3316 if (*varprefix !=
'\0')
3324 pg_log_debug(
"client %d pipeline ending, ongoing syncs: %d",
3328 pg_log_error(
"client %d failed to exit pipeline mode: %s", st->
id,
3346 pg_log_error(
"client %d script %d aborted in command %d query %d: %s",
3387 if (*argv[1] ==
':')
3389 if ((var =
getVariable(variables, argv[1] + 1)) == NULL)
3391 pg_log_error(
"%s: undefined variable \"%s\"", argv[0], argv[1] + 1);
3398 if (usec == 0 && !isdigit((
unsigned char) *var))
3400 pg_log_error(
"%s: invalid sleep time \"%s\" for variable \"%s\"",
3401 argv[0], var, argv[1] + 1);
3406 usec = atoi(argv[1]);
3478 pg_log_error(
"client %d aborted: failed to send a pipeline sync",
3501 pg_log_error(
"client %d aborted: failed to exit pipeline mode for rolling back the failed transaction",
3537 pg_log_error(
"unexpected transaction status %d", tx_status);
3561 "repeats the transaction after the error" :
3562 "ends the failed transaction"));
3641 if (st->
con == NULL)
3651 pg_log_error(
"client %d aborted while establishing connection", st->
id);
3759 if (now < st->txn_scheduled)
3776 if (command == NULL)
3782 pg_log_error(
"client %d aborted: end of script reached with pipeline open",
3805 commandFailed(st,
"gset",
"\\gset is not allowed in pipeline mode");
3811 commandFailed(st,
"aset",
"\\aset is not allowed in pipeline mode");
3965 commandFailed(st,
"SQL",
"perhaps the backend died while processing");
3999 if (now < st->sleep_until)
4063 pg_log_error(
"client %d aborted: failed to send sql command for rolling back the failed transaction",
4082 pg_log_error(
"perhaps the backend died while processing");
4084 pg_log_error(
"client %d aborted while receiving the transaction status", st->
id);
4100 pg_log_error(
"client %d aborted while rolling back the transaction after an error; perhaps the backend died while processing",
4129 pg_log_error(
"client %d aborted while rolling back the transaction after an error; %s",
4209 pg_log_error(
"client %d aborted: end of script reached without completing the last transaction",
4217 pg_log_error(
"perhaps the backend died while processing");
4219 pg_log_error(
"client %d aborted while receiving the transaction status", st->
id);
4292 argc = command->
argc;
4293 argv = command->
argv;
4302 for (
int i = 1;
i < argc;
i++)
4322 commandFailed(st,
"sleep",
"execution of meta-command failed");
4337 commandFailed(st, argv[0],
"evaluation of meta-command failed");
4343 commandFailed(st,
"set",
"assignment of meta-command failed");
4356 commandFailed(st, argv[0],
"evaluation of meta-command failed");
4379 commandFailed(st, argv[0],
"evaluation of meta-command failed");
4413 commandFailed(st,
"setshell",
"execution of meta-command failed");
4421 commandFailed(st,
"shell",
"execution of meta-command failed");
4433 commandFailed(st,
"startpipeline",
"cannot use pipeline mode with the simple query protocol");
4449 commandFailed(st,
"startpipeline",
"already in pipeline mode");
4454 commandFailed(st,
"startpipeline",
"failed to enter pipeline mode");
4467 commandFailed(st,
"syncpipeline",
"failed to send a pipeline sync");
4481 commandFailed(st,
"endpipeline",
"failed to send a pipeline sync");
4523 return "serialization";
4528 pg_fatal(
"unexpected error status: %d", estatus);
4546 StatsData *agg,
bool skipped,
double latency,
double lag)
4574 double lag_sum = 0.0;
4575 double lag_sum2 = 0.0;
4576 double lag_min = 0.0;
4577 double lag_max = 0.0;
4579 int64 serialization_failures = 0;
4580 int64 deadlock_failures = 0;
4623 serialization_failures,
4642 now / 1000000,
now % 1000000);
4668 double latency = 0.0,
4693 doLog(thread, st, agg, skipped, latency, lag);
4708 for (
i = 0;
i < length;
i++)
4718 fprintf(stderr,
"dropping old tables...\n");
4725 "pgbench_accounts, "
4726 "pgbench_branches, "
4756 "create%s table pgbench_accounts_%d\n"
4757 " partition of pgbench_accounts\n"
4758 " for values from (",
4783 "create%s table pgbench_accounts_%d\n"
4784 " partition of pgbench_accounts\n"
4785 " for values with (modulus %d, remainder %d)",
4824 const char *bigcols;
4825 int declare_fillfactor;
4827 static const struct ddlinfo DDLs[] = {
4830 "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
4831 "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)",
4836 "tid int not null,bid int,tbalance int,filler char(84)",
4837 "tid int not null,bid int,tbalance int,filler char(84)",
4842 "aid int not null,bid int,abalance int,filler char(84)",
4843 "aid bigint not null,bid int,abalance int,filler char(84)",
4848 "bid int not null,bbalance int,filler char(88)",
4849 "bid int not null,bbalance int,filler char(88)",
4856 fprintf(stderr,
"creating tables...\n");
4862 const struct ddlinfo *ddl = &DDLs[
i];
4874 else if (ddl->declare_fillfactor)
4882 char *escape_tablespace;
4905 "pgbench_accounts, "
4906 "pgbench_branches, "
4947 char copy_statement[256];
4948 const char *copy_statement_fmt =
"copy %s from stdin";
4949 int64 total = base *
scale;
4953 int log_interval = 1;
4956 char eol = isatty(fileno(stderr)) ?
'\r' :
'\n';
4966 if (strcmp(table,
"pgbench_accounts") != 0 ||
4968 copy_statement_fmt =
"copy %s from stdin with (freeze on)";
4971 n =
pg_snprintf(copy_statement,
sizeof(copy_statement), copy_statement_fmt, table);
4972 if (n >=
sizeof(copy_statement))
4973 pg_fatal(
"invalid buffer size: must be at least %d characters long", n);
4985 for (k = 0; k < total; k++)
5003 double remaining_sec = ((double) total -
j) * elapsed_sec /
j;
5007 (
int) ((
j * 100) / total),
5008 table, elapsed_sec, remaining_sec, eol);
5014 double remaining_sec = ((double) total -
j) * elapsed_sec /
j;
5021 (
int) ((
j * 100) / total),
5022 table, elapsed_sec, remaining_sec, eol);
5030 if (
chars != 0 && eol !=
'\n')
5034 pg_fatal(
"very last PQputline failed");
5050 fprintf(stderr,
"generating data (client-side)...\n");
5084 fprintf(stderr,
"generating data (server-side)...\n");
5098 "insert into pgbench_branches(bid,bbalance) "
5104 "insert into pgbench_tellers(tid,bid,tbalance) "
5105 "select tid, (tid - 1) / %d + 1, 0 "
5110 "insert into pgbench_accounts(aid,bid,abalance,filler) "
5111 "select aid, (aid - 1) / %d + 1, 0, '' "
5127 fprintf(stderr,
"vacuuming...\n");
5140 static const char *
const DDLINDEXes[] = {
5141 "alter table pgbench_branches add primary key (bid)",
5142 "alter table pgbench_tellers add primary key (tid)",
5143 "alter table pgbench_accounts add primary key (aid)"
5148 fprintf(stderr,
"creating primary keys...\n");
5158 char *escape_tablespace;
5178 static const char *
const DDLKEYs[] = {
5179 "alter table pgbench_tellers add constraint pgbench_tellers_bid_fkey foreign key (bid) references pgbench_branches",
5180 "alter table pgbench_accounts add constraint pgbench_accounts_bid_fkey foreign key (bid) references pgbench_branches",
5181 "alter table pgbench_history add constraint pgbench_history_bid_fkey foreign key (bid) references pgbench_branches",
5182 "alter table pgbench_history add constraint pgbench_history_tid_fkey foreign key (tid) references pgbench_tellers",
5183 "alter table pgbench_history add constraint pgbench_history_aid_fkey foreign key (aid) references pgbench_accounts"
5187 fprintf(stderr,
"creating foreign keys...\n");
5204 if (initialize_steps[0] ==
'\0')
5205 pg_fatal(
"no initialization steps specified");
5207 for (
const char *step = initialize_steps; *step !=
'\0'; step++)
5211 pg_log_error(
"unrecognized initialization step \"%c\"", *step);
5227 double run_time = 0.0;
5233 pg_fatal(
"could not create connection for initialization");
5238 for (step = initialize_steps; *step !=
'\0'; step++)
5250 op =
"create tables";
5254 op =
"client-side generate";
5258 op =
"server-side generate";
5266 op =
"primary keys";
5270 op =
"foreign keys";
5276 pg_log_error(
"unrecognized initialization step \"%c\"", *step);
5292 run_time += elapsed_sec;
5296 fprintf(stderr,
"done in %.2f s (%s).\n", run_time, stats.
data);
5315 res =
PQexec(con,
"select count(*) from pgbench_branches");
5323 pg_log_error_hint(
"Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".",
5330 pg_fatal(
"invalid count(*) from pgbench_branches: \"%s\"",
5336 pg_log_warning(
"scale option ignored, using count from pgbench_branches table (%d)",
5355 "select o.n, p.partstrat, pg_catalog.count(i.inhparent) "
5356 "from pg_catalog.pg_class as c "
5357 "join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) "
5358 "cross join lateral (select pg_catalog.array_position(pg_catalog.current_schemas(true), n.nspname)) as o(n) "
5359 "left join pg_catalog.pg_partitioned_table as p on (p.partrelid = c.oid) "
5360 "left join pg_catalog.pg_inherits as i on (c.oid = i.inhparent) "
5361 "where c.relname = 'pgbench_accounts' and o.n is not null "
5378 pg_log_error(
"no pgbench_accounts table found in search_path");
5379 pg_log_error_hint(
"Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".",
PQdb(con));
5394 if (strcmp(
ps,
"r") == 0)
5396 else if (strcmp(
ps,
"h") == 0)
5401 pg_fatal(
"unexpected partition method: \"%s\"",
ps);
5424 while ((p = strchr(p,
':')) != NULL)
5446 pg_log_error(
"statement has too many arguments (maximum is %d): %s",
5478 const char *line,
const char *command,
5479 const char *msg,
const char *more,
int column)
5488 if (column >= 0 && line == NULL)
5490 if (command != NULL)
5499 fprintf(stderr,
"%s\n", line);
5501 fprintf(stderr,
"%*c error found here\n", column + 1,
'^');
5515 char *p = sql_command;
5520 if (isspace((
unsigned char) *p))
5522 else if (strncmp(p,
"--", 2) == 0)
5524 p = strchr(p,
'\n');
5563 my_command->
argc = 0;
5566 memset(my_command->
argv, 0,
sizeof(my_command->
argv));
5568 my_command->
expr = NULL;
5581 for (
int i = 0;
i < command->
argc;
i++)
5600 static int prepnum = 0;
5606 buffer[strcspn(buffer,
"\n\r")] =
'\0';
5660 my_command->
argc = 0;
5665 offsets[
j] = word_offset;
5683 "missing argument", NULL, -1);
5685 offsets[
j] = word_offset;
5692 my_command->
argv[0]);
5725 "too many arguments", NULL, -1);
5727 offsets[
j] = word_offset;
5741 if (my_command->
argc < 2)
5743 "missing argument", NULL, -1);
5745 if (my_command->
argc > 3)
5747 "too many arguments", NULL,
5748 offsets[3] - start_offset);
5756 if (my_command->
argv[1][0] !=
':')
5758 char *
c = my_command->
argv[1];
5759 bool have_digit =
false;
5762 if (*
c ==
'+' || *
c ==
'-')
5766 if (*
c && isdigit((
unsigned char) *
c))
5770 while (*
c && isdigit((
unsigned char) *
c))
5775 if (my_command->
argc == 2 && have_digit)
5777 my_command->
argv[2] =
c;
5778 offsets[2] = offsets[1] + (
c - my_command->
argv[1]);
5779 my_command->
argc = 3;
5788 "invalid sleep time, must be an integer",
5789 my_command->
argv[1], offsets[1] - start_offset);
5794 if (my_command->
argc == 3)
5800 "unrecognized time unit, must be us, ms or s",
5801 my_command->
argv[2], offsets[2] - start_offset);
5806 if (my_command->
argc < 3)
5808 "missing argument", NULL, -1);
5812 if (my_command->
argc < 2)
5814 "missing command", NULL, -1);
5821 if (my_command->
argc != 1)
5823 "unexpected argument", NULL, -1);
5827 if (my_command->
argc > 2)
5829 "too many arguments", NULL, -1);
5835 "invalid command", NULL, -1);
5846 pg_fatal(
"condition error in script \"%s\" command %d: %s",
5860 for (
i = 0;
ps->commands[
i] != NULL;
i++)
5904 ParseScript(
const char *script,
const char *desc,
int weight)
5914 #define COMMANDS_ALLOC_NUM 128
5951 sr =
psql_scan(sstate, &line_buf, &prompt);
5958 ps.commands[
index++] = command;
5977 "\\gset must follow an SQL command",
5985 "\\gset must follow an SQL command",
5989 if (command->
argc <= 1 || command->
argv[1][0] ==
'\0')
6004 ps.commands[
index++] = command;
6013 if (
index >= alloc_num)
6044 size_t buflen = BUFSIZ;
6053 nread = fread(
buf + used, 1, BUFSIZ,
fd);
6082 else if ((
fd = fopen(
filename,
"r")) == NULL)
6111 fprintf(stderr,
"Available builtin scripts:\n");
6143 pg_log_error(
"ambiguous builtin name: %d builtin scripts found for prefix \"%s\"", found,
name);
6162 int namelen = sep -
option;
6168 strncpy(*script,
option, namelen);
6169 (*script)[namelen] =
'\0';
6173 wtmp = strtol(sep + 1, &badp, 10);
6174 if (errno != 0 || badp == sep + 1 || *badp !=
'\0')
6175 pg_fatal(
"invalid weight specification: %s", sep);
6176 if (wtmp > INT_MAX || wtmp < 0)
6177 pg_fatal(
"weight specification out of range (0 .. %d): %lld",
6178 INT_MAX, (
long long) wtmp);
6195 pg_fatal(
"empty command list for script \"%s\"", script->
desc);
6249 cur.serialization_failures +=
6255 cnt =
cur.cnt - last->
cnt;
6256 total_run = (
now - test_start) / 1000000.0;
6257 tps = 1000000.0 * cnt / run;
6260 latency = 0.001 * (
cur.latency.sum - last->
latency.
sum) / cnt;
6262 stdev = 0.001 * sqrt(sqlat - 1000000.0 * latency * latency);
6263 lag = 0.001 * (
cur.lag.sum - last->
lag.
sum) / cnt;
6267 latency = sqlat = stdev = lag = 0;
6274 snprintf(tbuf,
sizeof(tbuf),
"%.3f s",
6280 snprintf(tbuf,
sizeof(tbuf),
"%.1f s", total_run);
6284 "progress: %s, %.1f tps, lat %.3f ms stddev %.3f, " INT64_FORMAT " failed",
6285 tbuf, tps, latency, stdev, failures);
6289 fprintf(stderr,
", lag %.3f ms", lag);
6311 double latency = ss->
sum / ss->
count;
6312 double stddev = sqrt(ss->
sum2 / ss->
count - latency * latency);
6314 printf(
"%s average = %.3f ms\n", prefix, 0.001 * latency);
6315 printf(
"%s stddev = %.3f ms\n", prefix, 0.001 * stddev);
6324 int client_ver = PG_VERSION_NUM;
6326 if (server_ver != client_ver)
6337 sverbuf,
sizeof(sverbuf));
6341 printf(
_(
"%s (%s, server %s)\n"),
6346 printf(
"%s (%s)\n",
"pgbench", PG_VERSION);
6360 int64 total_cnt = total->
cnt + total->
skipped + failures;
6362 double tps = total->
cnt / bench_duration;
6365 printf(
"transaction type: %s\n",
6370 printf(
"partition method: %s\npartitions: %d\n",
6381 printf(
"number of transactions per client: %d\n",
nxacts);
6393 failures, 100.0 * failures / total_cnt);
6424 (total->
cnt > 0) ? 100.0 * latency_late / total->
cnt : 0.0);
6431 printf(
"latency average = %.3f ms%s\n",
6432 0.001 * total_duration *
nclients / total_cnt,
6433 failures > 0 ?
" (including failures)" :
"");
6444 printf(
"rate limit schedule lag: avg %.3f (max %.3f) ms\n",
6459 printf(
"average connection time = %.3f ms\n", 0.001 * conn_total_duration / (total->
cnt + failures));
6460 printf(
"tps = %f (including reconnection times)\n", tps);
6464 printf(
"initial connection time = %.3f ms\n", 0.001 * conn_elapsed_duration);
6465 printf(
"tps = %f (without initial connection time)\n", tps);
6479 int64 script_total_cnt =
6480 sstats->
cnt + sstats->
skipped + script_failures;
6482 printf(
"SQL script %d: %s\n"
6483 " - weight: %d (targets %.1f%% of total)\n"
6484 " - " INT64_FORMAT " transactions (%.1f%% of total, tps = %f)\n",
6489 100.0 * sstats->
cnt / total->
cnt,
6490 sstats->
cnt / bench_duration);
6494 100.0 * script_failures / script_total_cnt);
6513 100.0 * sstats->
retried / script_total_cnt);
6521 100.0 * sstats->
skipped / script_total_cnt);
6534 printf(
"%sstatement latencies in milliseconds%s:\n",
6538 ", failures and retries"));
6547 printf(
" %11.3f %10" INT64_MODIFIER
"d %s\n",
6548 (cstats->
count > 0) ?
6549 1000.0 * cstats->
sum / cstats->
count : 0.0,
6550 (*commands)->failures,
6551 (*commands)->first_line);
6553 printf(
" %11.3f %10" INT64_MODIFIER
"d %10" INT64_MODIFIER
"d %s\n",
6554 (cstats->
count > 0) ?
6555 1000.0 * cstats->
sum / cstats->
count : 0.0,
6556 (*commands)->failures,
6557 (*commands)->retries,
6558 (*commands)->first_line);
6574 if (seed == NULL || strcmp(seed,
"time") == 0)
6579 else if (strcmp(seed,
"rand") == 0)
6591 unsigned long ulseed;
6595 if (sscanf(seed,
"%lu%c", &ulseed, &garbage) != 1)
6597 pg_log_error(
"unrecognized random seed option \"%s\"", seed);
6601 iseed = (uint64) ulseed;
6605 pg_log_info(
"setting random seed to %llu", (
unsigned long long) iseed);
6616 main(
int argc,
char **argv)
6618 static struct option long_options[] = {
6668 bool is_init_mode =
false;
6669 char *initialize_steps = NULL;
6670 bool foreign_keys =
false;
6671 bool is_no_vacuum =
false;
6672 bool do_vacuum_accounts =
false;
6674 bool scale_given =
false;
6676 bool benchmarking_option_set =
false;
6677 bool initialization_option_set =
false;
6678 bool internal_script_used =
false;
6686 conn_total_duration;
6688 int64 latency_late = 0;
6695 #ifdef HAVE_GETRLIMIT
6717 if (strcmp(argv[1],
"--help") == 0 || strcmp(argv[1],
"-?") == 0)
6722 if (strcmp(argv[1],
"--version") == 0 || strcmp(argv[1],
"-V") == 0)
6724 puts(
"pgbench (PostgreSQL) " PG_VERSION);
6733 pg_fatal(
"error while setting random seed from PGBENCH_RANDOM_SEED environment variable");
6735 while ((
c =
getopt_long(argc, argv,
"b:c:CdD:f:F:h:iI:j:lL:M:nNp:P:qrR:s:St:T:U:v", long_options, &optindex)) != -1)
6742 if (strcmp(
optarg,
"list") == 0)
6749 benchmarking_option_set =
true;
6750 internal_script_used =
true;
6753 benchmarking_option_set =
true;
6759 #ifdef HAVE_GETRLIMIT
6760 if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
6764 pg_log_error(
"need at least %d open files, but system limit is %ld",
6765 nclients + 3, (
long) rlim.rlim_cur);
6766 pg_log_error_hint(
"Reduce number of clients, or use limit/ulimit to increase the system limit.");
6772 benchmarking_option_set =
true;
6782 benchmarking_option_set =
true;
6784 if ((p = strchr(
optarg,
'=')) == NULL || p ==
optarg || *(p + 1) ==
'\0')
6795 benchmarking_option_set =
true;
6798 initialization_option_set =
true;
6807 is_init_mode =
true;
6813 initialization_option_set =
true;
6816 benchmarking_option_set =
true;
6824 benchmarking_option_set =
true;
6829 double limit_ms = atof(
optarg);
6831 if (limit_ms <= 0.0)
6833 benchmarking_option_set =
true;
6838 benchmarking_option_set =
true;
6846 is_no_vacuum =
true;
6850 benchmarking_option_set =
true;
6851 internal_script_used =
true;
6857 benchmarking_option_set =
true;
6863 initialization_option_set =
true;
6867 benchmarking_option_set =
true;
6873 double throttle_value = atof(
optarg);
6875 benchmarking_option_set =
true;
6877 if (throttle_value <= 0.0)
6891 benchmarking_option_set =
true;
6892 internal_script_used =
true;
6895 benchmarking_option_set =
true;
6901 benchmarking_option_set =
true;
6910 benchmarking_option_set =
true;
6911 do_vacuum_accounts =
true;
6914 initialization_option_set =
true;
6918 initialization_option_set =
true;
6922 initialization_option_set =
true;
6926 benchmarking_option_set =
true;
6928 if (sample_rate <= 0.0 || sample_rate > 1.0)
6932 benchmarking_option_set =
true;
6939 benchmarking_option_set =
true;
6942 benchmarking_option_set =
true;
6946 initialization_option_set =
true;
6947 foreign_keys =
true;
6950 benchmarking_option_set =
true;
6952 pg_fatal(
"error while setting random seed from --random-seed option");
6963 initialization_option_set =
true;
6969 initialization_option_set =
true;
6975 pg_fatal(
"invalid partition method, expecting \"range\" or \"hash\", got: \"%s\"",
6979 benchmarking_option_set =
true;
6986 if (max_tries_arg < 0)
6989 benchmarking_option_set =
true;
6994 benchmarking_option_set =
true;
6998 benchmarking_option_set =
true;
7012 benchmarking_option_set =
true;
7013 internal_script_used =
true;
7021 for (
int j = 0; commands[
j] != NULL;
j++)
7030 pg_fatal(
"total script weight must not be zero");
7055 if ((env = getenv(
"PGDATABASE")) != NULL && *env !=
'\0')
7057 else if ((env = getenv(
"PGUSER")) != NULL && *env !=
'\0')
7065 pg_log_error(
"too many command-line arguments (first is \"%s\")",
7073 if (benchmarking_option_set)
7074 pg_fatal(
"some of the specified options cannot be used in initialization (-i) mode");
7077 pg_fatal(
"--partition-method requires greater than zero --partitions");
7083 if (initialize_steps == NULL)
7091 while ((p = strchr(initialize_steps,
'v')) != NULL)
7098 if (strchr(initialize_steps,
'f') == NULL)
7100 initialize_steps = (
char *)
7102 strlen(initialize_steps) + 2);
7103 strcat(initialize_steps,
"f");
7112 if (initialization_option_set)
7113 pg_fatal(
"some of the specified options cannot be used in benchmarking mode");
7117 pg_fatal(
"specify either a number of transactions (-t) or a duration (-T), not both");
7125 pg_fatal(
"log sampling (--sampling-rate) is allowed only when logging transactions (-l)");
7129 pg_fatal(
"log sampling (--sampling-rate) and aggregation (--aggregate-interval) cannot be used at the same time");
7132 pg_fatal(
"log aggregation is allowed only when actually logging transactions");
7135 pg_fatal(
"log file prefix (--log-prefix) is allowed only when logging transactions (-l)");
7144 pg_fatal(
"--progress-timestamp is allowed only under --progress");
7149 pg_fatal(
"an unlimited number of transaction tries can only be used with --latency-limit or a duration (-T)");
7169 for (
j = 0;
j <
state[0].variables.nvars;
j++)
7199 pg_fatal(
"could not create connection for setup");
7204 pg_log_debug(
"pghost: %s pgport: %s nclients: %d %s: %d dbName: %s",
7206 duration <= 0 ?
"nxacts" :
"duration",
7209 if (internal_script_used)
7258 fprintf(stderr,
"starting vacuum...");
7264 if (do_vacuum_accounts)
7266 fprintf(stderr,
"starting vacuum pgbench_accounts...");
7292 nclients_dealt += thread->
nstate;
7307 pg_fatal(
"could not initialize barrier: %m");
7318 pg_fatal(
"could not create thread: %m");
7331 conn_total_duration = 0;
7340 for (
int j = 0;
j < thread->
nstate;
j++)
7357 if (bench_start == 0 || thread->
bench_start < bench_start)
7381 pg_log_error(
"Run was aborted; the above results are incomplete.");
7392 int nstate = thread->
nstate;
7393 int remains = nstate;
7407 if (thread->
tid == 0)
7412 thread->
logfile = fopen(logpath,
"w");
7415 pg_fatal(
"could not open logfile \"%s\": %m", logpath);
7419 for (
int i = 0;
i < nstate;
i++)
7428 last_report = thread_start;
7429 next_report = last_report + (int64) 1000000 *
progress;
7435 for (
int i = 0;
i < nstate;
i++)
7440 pg_fatal(
"could not create connection for client %d",
7477 for (
int i = 0;
i < nstate;
i++)
7492 if (min_usec > this_usec)
7493 min_usec = this_usec;
7529 if (
now >= next_report)
7531 else if ((next_report -
now) < min_usec)
7532 min_usec = next_report -
now;
7581 for (
int i = 0;
i < nstate;
i++)
7630 if (now2 >= next_report)
7639 &last, &last_report);
7647 next_report += (int64) 1000000 *
progress;
7648 }
while (now2 >= next_report);
7659 for (
int i = 0;
i < nstate;
i++)
7663 pg_log_error(
"Run was aborted due to an error in thread %d",
7689 if (st->
con != NULL)
7717 static VOID CALLBACK
7718 win32_timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
7730 queue = CreateTimerQueue();
7731 if (seconds > ((DWORD) -1) / 1000 ||
7732 !CreateTimerQueueTimer(&timer, queue,
7733 win32_timer_callback, NULL, seconds * 1000, 0,
7734 WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE))
7776 #ifdef POLL_USING_PPOLL
7784 sizeof(
struct pollfd) * count);
7807 sa->pollfds[
idx].events = POLLIN;
7808 sa->pollfds[
idx].revents = 0;
7817 struct timespec timeout;
7819 timeout.tv_sec = usecs / 1000000;
7820 timeout.tv_nsec = (usecs % 1000000) * 1000;
7821 return ppoll(
sa->pollfds,
sa->curfds, &timeout, NULL);
7825 return ppoll(
sa->pollfds,
sa->curfds, NULL, NULL);
7840 if (
sa->curfds == 0)
7844 return (
sa->pollfds[
idx].revents & POLLIN) != 0;
7849 #ifdef POLL_USING_SELECT
7875 if (
sa->fds.fd_count + 1 >= FD_SETSIZE)
7877 pg_log_error(
"too many concurrent database clients for this platform: %d",
7878 sa->fds.fd_count + 1);
7882 if (fd < 0 || fd >= FD_SETSIZE)
7884 pg_log_error(
"socket file descriptor out of range for select(): %d",
7890 FD_SET(
fd, &
sa->fds);
7900 struct timeval timeout;
7902 timeout.tv_sec = usecs / 1000000;
7903 timeout.tv_usec = usecs % 1000000;
7904 return select(
sa->maxfd + 1, &
sa->fds, NULL, NULL, &timeout);
7908 return select(
sa->maxfd + 1, &
sa->fds, NULL, NULL, NULL);
7915 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 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)
Assert(fmt[strlen(fmt) - 1] !='\n')
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::@34::@35 variable
union PgBenchValue::@33 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]