PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pgbench.c
Go to the documentation of this file.
1/*
2 * pgbench.c
3 *
4 * A simple benchmark program for PostgreSQL
5 * Originally written by Tatsuo Ishii and enhanced by many contributors.
6 *
7 * src/bin/pgbench/pgbench.c
8 * Copyright (c) 2000-2025, PostgreSQL Global Development Group
9 * ALL RIGHTS RESERVED;
10 *
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose, without fee, and without a written agreement
13 * is hereby granted, provided that the above copyright notice and this
14 * paragraph and the following two paragraphs appear in all copies.
15 *
16 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
17 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
18 * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
19 * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
20 * POSSIBILITY OF SUCH DAMAGE.
21 *
22 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
25 * ON AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAS NO OBLIGATIONS TO
26 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
27 *
28 */
29
30#if defined(WIN32) && FD_SETSIZE < 1024
31#error FD_SETSIZE needs to have been increased
32#endif
33
34#include "postgres_fe.h"
35
36#include <ctype.h>
37#include <float.h>
38#include <limits.h>
39#include <math.h>
40#include <signal.h>
41#include <time.h>
42#include <sys/time.h>
43#include <sys/resource.h> /* for getrlimit */
44
45/* For testing, PGBENCH_USE_SELECT can be defined to force use of that code */
46#if defined(HAVE_PPOLL) && !defined(PGBENCH_USE_SELECT)
47#define POLL_USING_PPOLL
48#ifdef HAVE_POLL_H
49#include <poll.h>
50#endif
51#else /* no ppoll(), so use select() */
52#define POLL_USING_SELECT
53#include <sys/select.h>
54#endif
55
56#include "catalog/pg_class_d.h"
57#include "common/int.h"
58#include "common/logging.h"
59#include "common/pg_prng.h"
60#include "common/string.h"
61#include "common/username.h"
62#include "fe_utils/cancel.h"
66#include "getopt_long.h"
67#include "libpq-fe.h"
68#include "pgbench.h"
69#include "port/pg_bitutils.h"
71
72/* X/Open (XSI) requires <math.h> to provide M_PI, but core POSIX does not */
73#ifndef M_PI
74#define M_PI 3.14159265358979323846
75#endif
76
77#define ERRCODE_T_R_SERIALIZATION_FAILURE "40001"
78#define ERRCODE_T_R_DEADLOCK_DETECTED "40P01"
79#define ERRCODE_UNDEFINED_TABLE "42P01"
80
81/*
82 * Hashing constants
83 */
84#define FNV_PRIME UINT64CONST(0x100000001b3)
85#define FNV_OFFSET_BASIS UINT64CONST(0xcbf29ce484222325)
86#define MM2_MUL UINT64CONST(0xc6a4a7935bd1e995)
87#define MM2_MUL_TIMES_8 UINT64CONST(0x35253c9ade8f4ca8)
88#define MM2_ROT 47
89
90/*
91 * Multi-platform socket set implementations
92 */
93
94#ifdef POLL_USING_PPOLL
95#define SOCKET_WAIT_METHOD "ppoll"
96
97typedef struct socket_set
98{
99 int maxfds; /* allocated length of pollfds[] array */
100 int curfds; /* number currently in use */
101 struct pollfd pollfds[FLEXIBLE_ARRAY_MEMBER];
102} socket_set;
103
104#endif /* POLL_USING_PPOLL */
105
106#ifdef POLL_USING_SELECT
107#define SOCKET_WAIT_METHOD "select"
108
109typedef struct socket_set
110{
111 int maxfd; /* largest FD currently set in fds */
112 fd_set fds;
114
115#endif /* POLL_USING_SELECT */
116
117/*
118 * Multi-platform thread implementations
119 */
120
121#ifdef WIN32
122/* Use Windows threads */
123#include <windows.h>
124#define GETERRNO() (_dosmaperr(GetLastError()), errno)
125#define THREAD_T HANDLE
126#define THREAD_FUNC_RETURN_TYPE unsigned
127#define THREAD_FUNC_RETURN return 0
128#define THREAD_FUNC_CC __stdcall
129#define THREAD_CREATE(handle, function, arg) \
130 ((*(handle) = (HANDLE) _beginthreadex(NULL, 0, (function), (arg), 0, NULL)) == 0 ? errno : 0)
131#define THREAD_JOIN(handle) \
132 (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0 ? \
133 GETERRNO() : CloseHandle(handle) ? 0 : GETERRNO())
134#define THREAD_BARRIER_T SYNCHRONIZATION_BARRIER
135#define THREAD_BARRIER_INIT(barrier, n) \
136 (InitializeSynchronizationBarrier((barrier), (n), 0) ? 0 : GETERRNO())
137#define THREAD_BARRIER_WAIT(barrier) \
138 EnterSynchronizationBarrier((barrier), \
139 SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
140#define THREAD_BARRIER_DESTROY(barrier)
141#else
142/* Use POSIX threads */
143#include "port/pg_pthread.h"
144#define THREAD_T pthread_t
145#define THREAD_FUNC_RETURN_TYPE void *
146#define THREAD_FUNC_RETURN return NULL
147#define THREAD_FUNC_CC
148#define THREAD_CREATE(handle, function, arg) \
149 pthread_create((handle), NULL, (function), (arg))
150#define THREAD_JOIN(handle) \
151 pthread_join((handle), NULL)
152#define THREAD_BARRIER_T pthread_barrier_t
153#define THREAD_BARRIER_INIT(barrier, n) \
154 pthread_barrier_init((barrier), NULL, (n))
155#define THREAD_BARRIER_WAIT(barrier) pthread_barrier_wait((barrier))
156#define THREAD_BARRIER_DESTROY(barrier) pthread_barrier_destroy((barrier))
157#endif
158
159
160/********************************************************************
161 * some configurable parameters */
162
163#define DEFAULT_INIT_STEPS "dtgvp" /* default -I setting */
164#define ALL_INIT_STEPS "dtgGvpf" /* all possible steps */
165
166#define LOG_STEP_SECONDS 5 /* seconds between log messages */
167#define DEFAULT_NXACTS 10 /* default nxacts */
168
169#define MIN_GAUSSIAN_PARAM 2.0 /* minimum parameter for gauss */
170
171#define MIN_ZIPFIAN_PARAM 1.001 /* minimum parameter for zipfian */
172#define MAX_ZIPFIAN_PARAM 1000.0 /* maximum parameter for zipfian */
173
174static int nxacts = 0; /* number of transactions per client */
175static int duration = 0; /* duration in seconds */
176static int64 end_time = 0; /* when to stop in micro seconds, under -T */
177
178/*
179 * scaling factor. for example, scale = 10 will make 1000000 tuples in
180 * pgbench_accounts table.
181 */
182static int scale = 1;
183
184/*
185 * fillfactor. for example, fillfactor = 90 will use only 90 percent
186 * space during inserts and leave 10 percent free.
187 */
188static int fillfactor = 100;
189
190/*
191 * use unlogged tables?
192 */
193static bool unlogged_tables = false;
194
195/*
196 * log sampling rate (1.0 = log everything, 0.0 = option not given)
197 */
198static double sample_rate = 0.0;
199
200/*
201 * When threads are throttled to a given rate limit, this is the target delay
202 * to reach that rate in usec. 0 is the default and means no throttling.
203 */
204static double throttle_delay = 0;
205
206/*
207 * Transactions which take longer than this limit (in usec) are counted as
208 * late, and reported as such, although they are completed anyway. When
209 * throttling is enabled, execution time slots that are more than this late
210 * are skipped altogether, and counted separately.
211 */
213
214/*
215 * tablespace selection
216 */
217static char *tablespace = NULL;
218static char *index_tablespace = NULL;
219
220/*
221 * Number of "pgbench_accounts" partitions. 0 is the default and means no
222 * partitioning.
223 */
224static int partitions = 0;
225
226/* partitioning strategy for "pgbench_accounts" */
227typedef enum
228{
229 PART_NONE, /* no partitioning */
230 PART_RANGE, /* range partitioning */
231 PART_HASH, /* hash partitioning */
233
235static const char *const PARTITION_METHOD[] = {"none", "range", "hash"};
236
237/* random seed used to initialize base_random_sequence */
238static int64 random_seed = -1;
239
240/*
241 * end of configurable parameters
242 *********************************************************************/
243
244#define nbranches 1 /* Makes little sense to change this. Change
245 * -s instead */
246#define ntellers 10
247#define naccounts 100000
248
249/*
250 * The scale factor at/beyond which 32bit integers are incapable of storing
251 * 64bit values.
252 *
253 * Although the actual threshold is 21474, we use 20000 because it is easier to
254 * document and remember, and isn't that far away from the real threshold.
255 */
256#define SCALE_32BIT_THRESHOLD 20000
258static bool use_log; /* log transaction latencies to a file */
259static bool use_quiet; /* quiet logging onto stderr */
260static int agg_interval; /* log aggregates instead of individual
261 * transactions */
262static bool per_script_stats = false; /* whether to collect stats per script */
263static int progress = 0; /* thread progress report every this seconds */
264static bool progress_timestamp = false; /* progress report with Unix time */
265static int nclients = 1; /* number of clients */
266static int nthreads = 1; /* number of threads */
267static bool is_connect; /* establish connection for each transaction */
268static bool report_per_command = false; /* report per-command latencies,
269 * retries after errors and failures
270 * (errors without retrying) */
271static int main_pid; /* main process id used in log filename */
272
273/*
274 * There are different types of restrictions for deciding that the current
275 * transaction with a serialization/deadlock error can no longer be retried and
276 * should be reported as failed:
277 * - max_tries (--max-tries) can be used to limit the number of tries;
278 * - latency_limit (-L) can be used to limit the total time of tries;
279 * - duration (-T) can be used to limit the total benchmark time.
280 *
281 * They can be combined together, and you need to use at least one of them to
282 * retry the transactions with serialization/deadlock errors. If none of them is
283 * used, the default value of max_tries is 1 and such transactions will not be
284 * retried.
285 */
286
287/*
288 * We cannot retry a transaction after the serialization/deadlock error if its
289 * number of tries reaches this maximum; if its value is zero, it is not used.
290 */
291static uint32 max_tries = 1;
293static bool failures_detailed = false; /* whether to group failures in
294 * reports or logs by basic types */
296static const char *pghost = NULL;
297static const char *pgport = NULL;
298static const char *username = NULL;
299static const char *dbName = NULL;
300static char *logfile_prefix = NULL;
301static const char *progname;
303#define WSEP '@' /* weight separator */
305static volatile sig_atomic_t timer_exceeded = false; /* flag from signal
306 * handler */
307
308/*
309 * We don't want to allocate variables one by one; for efficiency, add a
310 * constant margin each time it overflows.
311 */
312#define VARIABLES_ALLOC_MARGIN 8
313
314/*
315 * Variable definitions.
316 *
317 * If a variable only has a string value, "svalue" is that value, and value is
318 * "not set". If the value is known, "value" contains the value (in any
319 * variant).
320 *
321 * In this case "svalue" contains the string equivalent of the value, if we've
322 * had occasion to compute that, or NULL if we haven't.
323 */
324typedef struct
326 char *name; /* variable's name */
327 char *svalue; /* its value in string form, if known */
328 PgBenchValue value; /* actual variable's value */
329} Variable;
330
331/*
332 * Data structure for client variables.
333 */
334typedef struct
336 Variable *vars; /* array of variable definitions */
337 int nvars; /* number of variables */
338
339 /*
340 * The maximum number of variables that we can currently store in 'vars'
341 * without having to reallocate more space. We must always have max_vars
342 * >= nvars.
343 */
344 int max_vars;
346 bool vars_sorted; /* are variables sorted by name? */
347} Variables;
349#define MAX_SCRIPTS 128 /* max number of SQL scripts allowed */
350#define SHELL_COMMAND_SIZE 256 /* maximum size allowed for shell command */
351
352/*
353 * Simple data structure to keep stats about something.
354 *
355 * XXX probably the first value should be kept and used as an offset for
356 * better numerical stability...
357 */
358typedef struct SimpleStats
360 int64 count; /* how many values were encountered */
361 double min; /* the minimum seen */
362 double max; /* the maximum seen */
363 double sum; /* sum of values */
364 double sum2; /* sum of squared values */
366
367/*
368 * The instr_time type is expensive when dealing with time arithmetic. Define
369 * a type to hold microseconds instead. Type int64 is good enough for about
370 * 584500 years.
371 */
372typedef int64 pg_time_usec_t;
373
374/*
375 * Data structure to hold various statistics: per-thread and per-script stats
376 * are maintained and merged together.
377 */
378typedef struct StatsData
380 pg_time_usec_t start_time; /* interval start time, for aggregates */
381
382 /*----------
383 * Transactions are counted depending on their execution and outcome.
384 * First a transaction may have started or not: skipped transactions occur
385 * under --rate and --latency-limit when the client is too late to execute
386 * them. Secondly, a started transaction may ultimately succeed or fail,
387 * possibly after some retries when --max-tries is not one. Thus
388 *
389 * the number of all transactions =
390 * 'skipped' (it was too late to execute them) +
391 * 'cnt' (the number of successful transactions) +
392 * 'failed' (the number of failed transactions).
393 *
394 * A successful transaction can have several unsuccessful tries before a
395 * successful run. Thus
396 *
397 * 'cnt' (the number of successful transactions) =
398 * successfully retried transactions (they got a serialization or a
399 * deadlock error(s), but were
400 * successfully retried from the very
401 * beginning) +
402 * directly successful transactions (they were successfully completed on
403 * the first try).
404 *
405 * A failed transaction is defined as unsuccessfully retried transactions.
406 * It can be one of two types:
407 *
408 * failed (the number of failed transactions) =
409 * 'serialization_failures' (they got a serialization error and were not
410 * successfully retried) +
411 * 'deadlock_failures' (they got a deadlock error and were not
412 * successfully retried).
413 *
414 * If the transaction was retried after a serialization or a deadlock
415 * error this does not guarantee that this retry was successful. Thus
416 *
417 * 'retries' (number of retries) =
418 * number of retries in all retried transactions =
419 * number of retries in (successfully retried transactions +
420 * failed transactions);
421 *
422 * 'retried' (number of all retried transactions) =
423 * successfully retried transactions +
424 * failed transactions.
425 *----------
426 */
427 int64 cnt; /* number of successful transactions, not
428 * including 'skipped' */
429 int64 skipped; /* number of transactions skipped under --rate
430 * and --latency-limit */
431 int64 retries; /* number of retries after a serialization or
432 * a deadlock error in all the transactions */
433 int64 retried; /* number of all transactions that were
434 * retried after a serialization or a deadlock
435 * error (perhaps the last try was
436 * unsuccessful) */
437 int64 serialization_failures; /* number of transactions that were
438 * not successfully retried after a
439 * serialization error */
440 int64 deadlock_failures; /* number of transactions that were not
441 * successfully retried after a deadlock
442 * error */
445} StatsData;
446
447/*
448 * For displaying Unix epoch timestamps, as some time functions may have
449 * another reference.
450 */
452
453/*
454 * Error status for errors during script execution.
455 */
456typedef enum EStatus
460
461 /* SQL errors */
465} EStatus;
466
467/*
468 * Transaction status at the end of a command.
469 */
470typedef enum TStatus
476} TStatus;
477
478/* Various random sequences are initialized from this one. */
480
481/* Synchronization barrier for start and connection */
483
484/*
485 * Connection state machine states.
486 */
487typedef enum
488{
489 /*
490 * The client must first choose a script to execute. Once chosen, it can
491 * either be throttled (state CSTATE_PREPARE_THROTTLE under --rate), start
492 * right away (state CSTATE_START_TX) or not start at all if the timer was
493 * exceeded (state CSTATE_FINISHED).
494 */
496
497 /*
498 * CSTATE_START_TX performs start-of-transaction processing. Establishes
499 * a new connection for the transaction in --connect mode, records the
500 * transaction start time, and proceed to the first command.
501 *
502 * Note: once a script is started, it will either error or run till its
503 * end, where it may be interrupted. It is not interrupted while running,
504 * so pgbench --time is to be understood as tx are allowed to start in
505 * that time, and will finish when their work is completed.
506 */
508
509 /*
510 * In CSTATE_PREPARE_THROTTLE state, we calculate when to begin the next
511 * transaction, and advance to CSTATE_THROTTLE. CSTATE_THROTTLE state
512 * sleeps until that moment, then advances to CSTATE_START_TX, or
513 * CSTATE_FINISHED if the next transaction would start beyond the end of
514 * the run.
515 */
518
519 /*
520 * We loop through these states, to process each command in the script:
521 *
522 * CSTATE_START_COMMAND starts the execution of a command. On a SQL
523 * command, the command is sent to the server, and we move to
524 * CSTATE_WAIT_RESULT state unless in pipeline mode. On a \sleep
525 * meta-command, the timer is set, and we enter the CSTATE_SLEEP state to
526 * wait for it to expire. Other meta-commands are executed immediately. If
527 * the command about to start is actually beyond the end of the script,
528 * advance to CSTATE_END_TX.
529 *
530 * CSTATE_WAIT_RESULT waits until we get a result set back from the server
531 * for the current command.
532 *
533 * CSTATE_SLEEP waits until the end of \sleep.
534 *
535 * CSTATE_END_COMMAND records the end-of-command timestamp, increments the
536 * command counter, and loops back to CSTATE_START_COMMAND state.
537 *
538 * CSTATE_SKIP_COMMAND is used by conditional branches which are not
539 * executed. It quickly skip commands that do not need any evaluation.
540 * This state can move forward several commands, till there is something
541 * to do or the end of the script.
542 */
548
549 /*
550 * States for failed commands.
551 *
552 * If the SQL/meta command fails, in CSTATE_ERROR clean up after an error:
553 * (1) clear the conditional stack; (2) if we have an unterminated
554 * (possibly failed) transaction block, send the rollback command to the
555 * server and wait for the result in CSTATE_WAIT_ROLLBACK_RESULT. If
556 * something goes wrong with rolling back, go to CSTATE_ABORTED.
557 *
558 * But if everything is ok we are ready for future transactions: if this
559 * is a serialization or deadlock error and we can re-execute the
560 * transaction from the very beginning, go to CSTATE_RETRY; otherwise go
561 * to CSTATE_FAILURE.
562 *
563 * In CSTATE_RETRY report an error, set the same parameters for the
564 * transaction execution as in the previous tries and process the first
565 * transaction command in CSTATE_START_COMMAND.
566 *
567 * In CSTATE_FAILURE report a failure, set the parameters for the
568 * transaction execution as they were before the first run of this
569 * transaction (except for a random state) and go to CSTATE_END_TX to
570 * complete this transaction.
571 */
576
577 /*
578 * CSTATE_END_TX performs end-of-transaction processing. It calculates
579 * latency, and logs the transaction. In --connect mode, it closes the
580 * current connection.
581 *
582 * Then either starts over in CSTATE_CHOOSE_SCRIPT, or enters
583 * CSTATE_FINISHED if we have no more work to do.
584 */
586
587 /*
588 * Final states. CSTATE_ABORTED means that the script execution was
589 * aborted because a command failed, CSTATE_FINISHED means success.
590 */
594
595/*
596 * Connection state.
597 */
598typedef struct
600 PGconn *con; /* connection handle to DB */
601 int id; /* client No. */
602 ConnectionStateEnum state; /* state machine's current state. */
603 ConditionalStack cstack; /* enclosing conditionals state */
604
605 /*
606 * Separate randomness for each client. This is used for random functions
607 * PGBENCH_RANDOM_* during the execution of the script.
608 */
609 pg_prng_state cs_func_rs;
611 int use_file; /* index in sql_script for this client */
612 int command; /* command number in script */
613 int num_syncs; /* number of ongoing sync commands */
614
615 /* client variables */
616 Variables variables;
617
618 /* various times about current transaction in microseconds */
619 pg_time_usec_t txn_scheduled; /* scheduled start time of transaction */
620 pg_time_usec_t sleep_until; /* scheduled start time of next cmd */
621 pg_time_usec_t txn_begin; /* used for measuring schedule lag times */
622 pg_time_usec_t stmt_begin; /* used for measuring statement latencies */
623
624 /* whether client prepared each command of each script */
625 bool **prepared;
626
627 /*
628 * For processing failures and repeating transactions with serialization
629 * or deadlock errors:
630 */
631 EStatus estatus; /* the error status of the current transaction
632 * execution; this is ESTATUS_NO_ERROR if
633 * there were no errors */
634 pg_prng_state random_state; /* random state */
635 uint32 tries; /* how many times have we already tried the
636 * current transaction? */
637
638 /* per client collected stats */
639 int64 cnt; /* client transaction count, for -t; skipped
640 * and failed transactions are also counted
641 * here */
642} CState;
643
644/*
645 * Thread state
646 */
647typedef struct
649 int tid; /* thread id */
650 THREAD_T thread; /* thread handle */
651 CState *state; /* array of CState */
652 int nstate; /* length of state[] */
653
654 /*
655 * Separate randomness for each thread. Each thread option uses its own
656 * random state to make all of them independent of each other and
657 * therefore deterministic at the thread level.
658 */
659 pg_prng_state ts_choose_rs; /* random state for selecting a script */
660 pg_prng_state ts_throttle_rs; /* random state for transaction throttling */
661 pg_prng_state ts_sample_rs; /* random state for log sampling */
663 int64 throttle_trigger; /* previous/next throttling (us) */
664 FILE *logfile; /* where to log, or NULL */
665
666 /* per thread collected stats in microseconds */
667 pg_time_usec_t create_time; /* thread creation time */
668 pg_time_usec_t started_time; /* thread is running */
669 pg_time_usec_t bench_start; /* thread is benchmarking */
670 pg_time_usec_t conn_duration; /* cumulated connection and disconnection
671 * delays */
674 int64 latency_late; /* count executed but late transactions */
675} TState;
676
677/*
678 * queries read from files
679 */
680#define SQL_COMMAND 1
681#define META_COMMAND 2
682
683/*
684 * max number of backslash command arguments or SQL variables,
685 * including the command or SQL statement itself
686 */
687#define MAX_ARGS 256
689typedef enum MetaCommand
691 META_NONE, /* not a known meta-command */
692 META_SET, /* \set */
693 META_SETSHELL, /* \setshell */
694 META_SHELL, /* \shell */
695 META_SLEEP, /* \sleep */
696 META_GSET, /* \gset */
697 META_ASET, /* \aset */
698 META_IF, /* \if */
699 META_ELIF, /* \elif */
700 META_ELSE, /* \else */
701 META_ENDIF, /* \endif */
702 META_STARTPIPELINE, /* \startpipeline */
703 META_SYNCPIPELINE, /* \syncpipeline */
704 META_ENDPIPELINE, /* \endpipeline */
707typedef enum QueryMode
709 QUERY_SIMPLE, /* simple query */
710 QUERY_EXTENDED, /* extended query */
711 QUERY_PREPARED, /* extended query with prepared statements */
713} QueryMode;
716static const char *const QUERYMODE[] = {"simple", "extended", "prepared"};
717
718/*
719 * struct Command represents one command in a script.
720 *
721 * lines The raw, possibly multi-line command text. Variable substitution
722 * not applied.
723 * first_line A short, single-line extract of 'lines', for error reporting.
724 * type SQL_COMMAND or META_COMMAND
725 * meta The type of meta-command, with META_NONE/GSET/ASET if command
726 * is SQL.
727 * argc Number of arguments of the command, 0 if not yet processed.
728 * argv Command arguments, the first of which is the command or SQL
729 * string itself. For SQL commands, after post-processing
730 * argv[0] is the same as 'lines' with variables substituted.
731 * prepname The name that this command is prepared under, in prepare mode
732 * varprefix SQL commands terminated with \gset or \aset have this set
733 * to a non NULL value. If nonempty, it's used to prefix the
734 * variable name that receives the value.
735 * aset do gset on all possible queries of a combined query (\;).
736 * expr Parsed expression, if needed.
737 * stats Time spent in this command.
738 * retries Number of retries after a serialization or deadlock error in the
739 * current command.
740 * failures Number of errors in the current command that were not retried.
741 */
742typedef struct Command
746 int type;
748 int argc;
750 char *prepname;
756} Command;
758typedef struct ParsedScript
760 const char *desc; /* script descriptor (eg, file name) */
761 int weight; /* selection weight */
762 Command **commands; /* NULL-terminated array of Commands */
763 StatsData stats; /* total time spent in script */
766static ParsedScript sql_script[MAX_SCRIPTS]; /* SQL script files */
767static int num_scripts; /* number of scripts in sql_script[] */
768static int64 total_weight = 0;
770static bool verbose_errors = false; /* print verbose messages of all errors */
772static bool exit_on_abort = false; /* exit when any client is aborted */
773
774/* Builtin test scripts */
775typedef struct BuiltinScript
777 const char *name; /* very short name for -b ... */
778 const char *desc; /* short description */
779 const char *script; /* actual pgbench script */
782static const BuiltinScript builtin_script[] =
783{
784 {
785 "tpcb-like",
786 "<builtin: TPC-B (sort of)>",
787 "\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
788 "\\set bid random(1, " CppAsString2(nbranches) " * :scale)\n"
789 "\\set tid random(1, " CppAsString2(ntellers) " * :scale)\n"
790 "\\set delta random(-5000, 5000)\n"
791 "BEGIN;\n"
792 "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
793 "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
794 "UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\n"
795 "UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\n"
796 "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
797 "END;\n"
798 },
799 {
800 "simple-update",
801 "<builtin: simple update>",
802 "\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
803 "\\set bid random(1, " CppAsString2(nbranches) " * :scale)\n"
804 "\\set tid random(1, " CppAsString2(ntellers) " * :scale)\n"
805 "\\set delta random(-5000, 5000)\n"
806 "BEGIN;\n"
807 "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
808 "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
809 "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
810 "END;\n"
811 },
812 {
813 "select-only",
814 "<builtin: select only>",
815 "\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
816 "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
817 }
818};
819
820
821/* Function prototypes */
822static void setNullValue(PgBenchValue *pv);
823static void setBoolValue(PgBenchValue *pv, bool bval);
824static void setIntValue(PgBenchValue *pv, int64 ival);
825static void setDoubleValue(PgBenchValue *pv, double dval);
826static bool evaluateExpr(CState *st, PgBenchExpr *expr,
827 PgBenchValue *retval);
829static void doLog(TState *thread, CState *st,
830 StatsData *agg, bool skipped, double latency, double lag);
831static void processXactStats(TState *thread, CState *st, pg_time_usec_t *now,
832 bool skipped, StatsData *agg);
833static void addScript(const ParsedScript *script);
835static void finishCon(CState *st);
836static void setalarm(int seconds);
837static socket_set *alloc_socket_set(int count);
838static void free_socket_set(socket_set *sa);
839static void clear_socket_set(socket_set *sa);
840static void add_socket_to_set(socket_set *sa, int fd, int idx);
841static int wait_on_socket_set(socket_set *sa, int64 usecs);
842static bool socket_has_input(socket_set *sa, int fd, int idx);
843
844/* callback used to build rows for COPY during data loading */
845typedef void (*initRowMethod) (PQExpBufferData *sql, int64 curr);
846
847/* callback functions for our flex lexer */
849 NULL, /* don't need get_variable functionality */
850};
851
852static char
853get_table_relkind(PGconn *con, const char *table)
854{
855 PGresult *res;
856 char *val;
857 char relkind;
858 const char *params[1] = {table};
859 const char *sql =
860 "SELECT relkind FROM pg_catalog.pg_class WHERE oid=$1::pg_catalog.regclass";
861
862 res = PQexecParams(con, sql, 1, NULL, params, NULL, NULL, 0);
864 {
865 pg_log_error("query failed: %s", PQerrorMessage(con));
866 pg_log_error_detail("Query was: %s", sql);
867 exit(1);
868 }
869 val = PQgetvalue(res, 0, 0);
870 Assert(strlen(val) == 1);
871 relkind = val[0];
872 PQclear(res);
873
874 return relkind;
875}
876
877static inline pg_time_usec_t
878pg_time_now(void)
879{
881
883
885}
886
887static inline void
889{
890 if ((*now) == 0)
891 (*now) = pg_time_now();
892}
894#define PG_TIME_GET_DOUBLE(t) (0.000001 * (t))
895
896static void
897usage(void)
898{
899 printf("%s is a benchmarking tool for PostgreSQL.\n\n"
900 "Usage:\n"
901 " %s [OPTION]... [DBNAME]\n"
902 "\nInitialization options:\n"
903 " -i, --initialize invokes initialization mode\n"
904 " -I, --init-steps=[" ALL_INIT_STEPS "]+ (default \"" DEFAULT_INIT_STEPS "\")\n"
905 " run selected initialization steps, in the specified order\n"
906 " d: drop any existing pgbench tables\n"
907 " t: create the tables used by the standard pgbench scenario\n"
908 " g: generate data, client-side\n"
909 " G: generate data, server-side\n"
910 " v: invoke VACUUM on the standard tables\n"
911 " p: create primary key indexes on the standard tables\n"
912 " f: create foreign keys between the standard tables\n"
913 " -F, --fillfactor=NUM set fill factor\n"
914 " -n, --no-vacuum do not run VACUUM during initialization\n"
915 " -q, --quiet quiet logging (one message each 5 seconds)\n"
916 " -s, --scale=NUM scaling factor\n"
917 " --foreign-keys create foreign key constraints between tables\n"
918 " --index-tablespace=TABLESPACE\n"
919 " create indexes in the specified tablespace\n"
920 " --partition-method=(range|hash)\n"
921 " partition pgbench_accounts with this method (default: range)\n"
922 " --partitions=NUM partition pgbench_accounts into NUM parts (default: 0)\n"
923 " --tablespace=TABLESPACE create tables in the specified tablespace\n"
924 " --unlogged-tables create tables as unlogged tables\n"
925 "\nOptions to select what to run:\n"
926 " -b, --builtin=NAME[@W] add builtin script NAME weighted at W (default: 1)\n"
927 " (use \"-b list\" to list available scripts)\n"
928 " -f, --file=FILENAME[@W] add script FILENAME weighted at W (default: 1)\n"
929 " -N, --skip-some-updates skip updates of pgbench_tellers and pgbench_branches\n"
930 " (same as \"-b simple-update\")\n"
931 " -S, --select-only perform SELECT-only transactions\n"
932 " (same as \"-b select-only\")\n"
933 "\nBenchmarking options:\n"
934 " -c, --client=NUM number of concurrent database clients (default: 1)\n"
935 " -C, --connect establish new connection for each transaction\n"
936 " -D, --define=VARNAME=VALUE\n"
937 " define variable for use by custom script\n"
938 " -j, --jobs=NUM number of threads (default: 1)\n"
939 " -l, --log write transaction times to log file\n"
940 " -L, --latency-limit=NUM count transactions lasting more than NUM ms as late\n"
941 " -M, --protocol=simple|extended|prepared\n"
942 " protocol for submitting queries (default: simple)\n"
943 " -n, --no-vacuum do not run VACUUM before tests\n"
944 " -P, --progress=NUM show thread progress report every NUM seconds\n"
945 " -r, --report-per-command report latencies, failures, and retries per command\n"
946 " -R, --rate=NUM target rate in transactions per second\n"
947 " -s, --scale=NUM report this scale factor in output\n"
948 " -t, --transactions=NUM number of transactions each client runs (default: 10)\n"
949 " -T, --time=NUM duration of benchmark test in seconds\n"
950 " -v, --vacuum-all vacuum all four standard tables before tests\n"
951 " --aggregate-interval=NUM aggregate data over NUM seconds\n"
952 " --exit-on-abort exit when any client is aborted\n"
953 " --failures-detailed report the failures grouped by basic types\n"
954 " --log-prefix=PREFIX prefix for transaction time log file\n"
955 " (default: \"pgbench_log\")\n"
956 " --max-tries=NUM max number of tries to run transaction (default: 1)\n"
957 " --progress-timestamp use Unix epoch timestamps for progress\n"
958 " --random-seed=SEED set random seed (\"time\", \"rand\", integer)\n"
959 " --sampling-rate=NUM fraction of transactions to log (e.g., 0.01 for 1%%)\n"
960 " --show-script=NAME show builtin script code, then exit\n"
961 " --verbose-errors print messages of all errors\n"
962 "\nCommon options:\n"
963 " --debug print debugging output\n"
964 " -d, --dbname=DBNAME database name to connect to\n"
965 " -h, --host=HOSTNAME database server host or socket directory\n"
966 " -p, --port=PORT database server port number\n"
967 " -U, --username=USERNAME connect as specified database user\n"
968 " -V, --version output version information, then exit\n"
969 " -?, --help show this help, then exit\n"
970 "\n"
971 "Report bugs to <%s>.\n"
972 "%s home page: <%s>\n",
973 progname, progname, PACKAGE_BUGREPORT, PACKAGE_NAME, PACKAGE_URL);
974}
975
976/* return whether str matches "^\s*[-+]?[0-9]+$" */
977static bool
978is_an_int(const char *str)
979{
980 const char *ptr = str;
981
982 /* skip leading spaces; cast is consistent with strtoint64 */
983 while (*ptr && isspace((unsigned char) *ptr))
984 ptr++;
985
986 /* skip sign */
987 if (*ptr == '+' || *ptr == '-')
988 ptr++;
989
990 /* at least one digit */
991 if (*ptr && !isdigit((unsigned char) *ptr))
992 return false;
993
994 /* eat all digits */
995 while (*ptr && isdigit((unsigned char) *ptr))
996 ptr++;
997
998 /* must have reached end of string */
999 return *ptr == '\0';
1000}
1001
1002
1003/*
1004 * strtoint64 -- convert a string to 64-bit integer
1005 *
1006 * This function is a slightly modified version of pg_strtoint64() from
1007 * src/backend/utils/adt/numutils.c.
1008 *
1009 * The function returns whether the conversion worked, and if so
1010 * "*result" is set to the result.
1011 *
1012 * If not errorOK, an error message is also printed out on errors.
1013 */
1014bool
1015strtoint64(const char *str, bool errorOK, int64 *result)
1016{
1017 const char *ptr = str;
1018 int64 tmp = 0;
1019 bool neg = false;
1020
1021 /*
1022 * Do our own scan, rather than relying on sscanf which might be broken
1023 * for long long.
1024 *
1025 * As INT64_MIN can't be stored as a positive 64 bit integer, accumulate
1026 * value as a negative number.
1027 */
1028
1029 /* skip leading spaces */
1030 while (*ptr && isspace((unsigned char) *ptr))
1031 ptr++;
1032
1033 /* handle sign */
1034 if (*ptr == '-')
1035 {
1036 ptr++;
1037 neg = true;
1038 }
1039 else if (*ptr == '+')
1040 ptr++;
1041
1042 /* require at least one digit */
1043 if (unlikely(!isdigit((unsigned char) *ptr)))
1044 goto invalid_syntax;
1045
1046 /* process digits */
1047 while (*ptr && isdigit((unsigned char) *ptr))
1048 {
1049 int8 digit = (*ptr++ - '0');
1050
1051 if (unlikely(pg_mul_s64_overflow(tmp, 10, &tmp)) ||
1052 unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
1053 goto out_of_range;
1054 }
1055
1056 /* allow trailing whitespace, but not other trailing chars */
1057 while (*ptr != '\0' && isspace((unsigned char) *ptr))
1058 ptr++;
1059
1060 if (unlikely(*ptr != '\0'))
1061 goto invalid_syntax;
1062
1063 if (!neg)
1064 {
1065 if (unlikely(tmp == PG_INT64_MIN))
1066 goto out_of_range;
1067 tmp = -tmp;
1068 }
1069
1070 *result = tmp;
1071 return true;
1072
1073out_of_range:
1074 if (!errorOK)
1075 pg_log_error("value \"%s\" is out of range for type bigint", str);
1076 return false;
1077
1078invalid_syntax:
1079 if (!errorOK)
1080 pg_log_error("invalid input syntax for type bigint: \"%s\"", str);
1081 return false;
1082}
1083
1084/* convert string to double, detecting overflows/underflows */
1085bool
1086strtodouble(const char *str, bool errorOK, double *dv)
1087{
1088 char *end;
1089
1090 errno = 0;
1091 *dv = strtod(str, &end);
1092
1093 if (unlikely(errno != 0))
1094 {
1095 if (!errorOK)
1096 pg_log_error("value \"%s\" is out of range for type double", str);
1097 return false;
1098 }
1099
1100 if (unlikely(end == str || *end != '\0'))
1101 {
1102 if (!errorOK)
1103 pg_log_error("invalid input syntax for type double: \"%s\"", str);
1104 return false;
1105 }
1106 return true;
1107}
1108
1109/*
1110 * Initialize a prng state struct.
1111 *
1112 * We derive the seed from base_random_sequence, which must be set up already.
1113 */
1114static void
1116{
1118}
1119
1120
1121/*
1122 * random number generator: uniform distribution from min to max inclusive.
1123 *
1124 * Although the limits are expressed as int64, you can't generate the full
1125 * int64 range in one call, because the difference of the limits mustn't
1126 * overflow int64. This is not checked.
1127 */
1128static int64
1130{
1131 return min + (int64) pg_prng_uint64_range(state, 0, max - min);
1132}
1133
1134/*
1135 * random number generator: exponential distribution from min to max inclusive.
1136 * the parameter is so that the density of probability for the last cut-off max
1137 * value is exp(-parameter).
1138 */
1139static int64
1141 double parameter)
1142{
1143 double cut,
1144 uniform,
1145 rand;
1146
1147 /* abort if wrong parameter, but must really be checked beforehand */
1148 Assert(parameter > 0.0);
1149 cut = exp(-parameter);
1150 /* pg_prng_double value in [0, 1), uniform in (0, 1] */
1151 uniform = 1.0 - pg_prng_double(state);
1152
1153 /*
1154 * inner expression in (cut, 1] (if parameter > 0), rand in [0, 1)
1155 */
1156 Assert((1.0 - cut) != 0.0);
1157 rand = -log(cut + (1.0 - cut) * uniform) / parameter;
1158 /* return int64 random number within between min and max */
1159 return min + (int64) ((max - min + 1) * rand);
1160}
1161
1162/* random number generator: gaussian distribution from min to max inclusive */
1163static int64
1165 double parameter)
1166{
1167 double stdev;
1168 double rand;
1169
1170 /* abort if parameter is too low, but must really be checked beforehand */
1171 Assert(parameter >= MIN_GAUSSIAN_PARAM);
1172
1173 /*
1174 * Get normally-distributed random number in the range -parameter <= stdev
1175 * < parameter.
1176 *
1177 * This loop is executed until the number is in the expected range.
1178 *
1179 * As the minimum parameter is 2.0, the probability of looping is low:
1180 * sqrt(-2 ln(r)) <= 2 => r >= e^{-2} ~ 0.135, then when taking the
1181 * average sinus multiplier as 2/pi, we have a 8.6% looping probability in
1182 * the worst case. For a parameter value of 5.0, the looping probability
1183 * is about e^{-5} * 2 / pi ~ 0.43%.
1184 */
1185 do
1186 {
1188 }
1189 while (stdev < -parameter || stdev >= parameter);
1190
1191 /* stdev is in [-parameter, parameter), normalization to [0,1) */
1192 rand = (stdev + parameter) / (parameter * 2.0);
1193
1194 /* return int64 random number within between min and max */
1195 return min + (int64) ((max - min + 1) * rand);
1196}
1197
1198/*
1199 * random number generator: generate a value, such that the series of values
1200 * will approximate a Poisson distribution centered on the given value.
1201 *
1202 * Individual results are rounded to integers, though the center value need
1203 * not be one.
1204 */
1205static int64
1206getPoissonRand(pg_prng_state *state, double center)
1207{
1208 /*
1209 * Use inverse transform sampling to generate a value > 0, such that the
1210 * expected (i.e. average) value is the given argument.
1211 */
1212 double uniform;
1213
1214 /* pg_prng_double value in [0, 1), uniform in (0, 1] */
1215 uniform = 1.0 - pg_prng_double(state);
1216
1217 return (int64) (-log(uniform) * center + 0.5);
1218}
1219
1220/*
1221 * Computing zipfian using rejection method, based on
1222 * "Non-Uniform Random Variate Generation",
1223 * Luc Devroye, p. 550-551, Springer 1986.
1224 *
1225 * This works for s > 1.0, but may perform badly for s very close to 1.0.
1226 */
1227static int64
1229{
1230 double b = pow(2.0, s - 1.0);
1231 double x,
1232 t,
1233 u,
1234 v;
1235
1236 /* Ensure n is sane */
1237 if (n <= 1)
1238 return 1;
1239
1240 while (true)
1241 {
1242 /* random variates */
1243 u = pg_prng_double(state);
1244 v = pg_prng_double(state);
1245
1246 x = floor(pow(u, -1.0 / (s - 1.0)));
1247
1248 t = pow(1.0 + 1.0 / x, s - 1.0);
1249 /* reject if too large or out of bound */
1250 if (v * x * (t - 1.0) / (b - 1.0) <= t / b && x <= n)
1251 break;
1252 }
1253 return (int64) x;
1254}
1255
1256/* random number generator: zipfian distribution from min to max inclusive */
1257static int64
1258getZipfianRand(pg_prng_state *state, int64 min, int64 max, double s)
1259{
1260 int64 n = max - min + 1;
1261
1262 /* abort if parameter is invalid */
1264
1265 return min - 1 + computeIterativeZipfian(state, n, s);
1266}
1267
1268/*
1269 * FNV-1a hash function
1270 */
1271static int64
1273{
1274 int64 result;
1275 int i;
1276
1277 result = FNV_OFFSET_BASIS ^ seed;
1278 for (i = 0; i < 8; ++i)
1279 {
1280 int32 octet = val & 0xff;
1281
1282 val = val >> 8;
1283 result = result ^ octet;
1284 result = result * FNV_PRIME;
1285 }
1286
1287 return result;
1288}
1289
1290/*
1291 * Murmur2 hash function
1292 *
1293 * Based on original work of Austin Appleby
1294 * https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp
1295 */
1296static int64
1298{
1299 uint64 result = seed ^ MM2_MUL_TIMES_8; /* sizeof(int64) */
1300 uint64 k = (uint64) val;
1301
1302 k *= MM2_MUL;
1303 k ^= k >> MM2_ROT;
1304 k *= MM2_MUL;
1305
1306 result ^= k;
1307 result *= MM2_MUL;
1308
1309 result ^= result >> MM2_ROT;
1310 result *= MM2_MUL;
1311 result ^= result >> MM2_ROT;
1312
1313 return (int64) result;
1314}
1315
1316/*
1317 * Pseudorandom permutation function
1318 *
1319 * For small sizes, this generates each of the (size!) possible permutations
1320 * of integers in the range [0, size) with roughly equal probability. Once
1321 * the size is larger than 20, the number of possible permutations exceeds the
1322 * number of distinct states of the internal pseudorandom number generator,
1323 * and so not all possible permutations can be generated, but the permutations
1324 * chosen should continue to give the appearance of being random.
1325 *
1326 * THIS FUNCTION IS NOT CRYPTOGRAPHICALLY SECURE.
1327 * DO NOT USE FOR SUCH PURPOSE.
1328 */
1329static int64
1330permute(const int64 val, const int64 isize, const int64 seed)
1331{
1332 /* using a high-end PRNG is probably overkill */
1334 uint64 size;
1335 uint64 v;
1336 int masklen;
1337 uint64 mask;
1338 int i;
1339
1340 if (isize < 2)
1341 return 0; /* nothing to permute */
1342
1343 /* Initialize prng state using the seed */
1344 pg_prng_seed(&state, (uint64) seed);
1345
1346 /* Computations are performed on unsigned values */
1347 size = (uint64) isize;
1348 v = (uint64) val % size;
1349
1350 /* Mask to work modulo largest power of 2 less than or equal to size */
1351 masklen = pg_leftmost_one_pos64(size);
1352 mask = (((uint64) 1) << masklen) - 1;
1353
1354 /*
1355 * Permute the input value by applying several rounds of pseudorandom
1356 * bijective transformations. The intention here is to distribute each
1357 * input uniformly randomly across the range, and separate adjacent inputs
1358 * approximately uniformly randomly from each other, leading to a fairly
1359 * random overall choice of permutation.
1360 *
1361 * To separate adjacent inputs, we multiply by a random number modulo
1362 * (mask + 1), which is a power of 2. For this to be a bijection, the
1363 * multiplier must be odd. Since this is known to lead to less randomness
1364 * in the lower bits, we also apply a rotation that shifts the topmost bit
1365 * into the least significant bit. In the special cases where size <= 3,
1366 * mask = 1 and each of these operations is actually a no-op, so we also
1367 * XOR the value with a different random number to inject additional
1368 * randomness. Since the size is generally not a power of 2, we apply
1369 * this bijection on overlapping upper and lower halves of the input.
1370 *
1371 * To distribute the inputs uniformly across the range, we then also apply
1372 * a random offset modulo the full range.
1373 *
1374 * Taken together, these operations resemble a modified linear
1375 * congruential generator, as is commonly used in pseudorandom number
1376 * generators. The number of rounds is fairly arbitrary, but six has been
1377 * found empirically to give a fairly good tradeoff between performance
1378 * and uniform randomness. For small sizes it selects each of the (size!)
1379 * possible permutations with roughly equal probability. For larger
1380 * sizes, not all permutations can be generated, but the intended random
1381 * spread is still produced.
1382 */
1383 for (i = 0; i < 6; i++)
1384 {
1385 uint64 m,
1386 r,
1387 t;
1388
1389 /* Random multiply (by an odd number), XOR and rotate of lower half */
1390 m = (pg_prng_uint64(&state) & mask) | 1;
1391 r = pg_prng_uint64(&state) & mask;
1392 if (v <= mask)
1393 {
1394 v = ((v * m) ^ r) & mask;
1395 v = ((v << 1) & mask) | (v >> (masklen - 1));
1396 }
1397
1398 /* Random multiply (by an odd number), XOR and rotate of upper half */
1399 m = (pg_prng_uint64(&state) & mask) | 1;
1400 r = pg_prng_uint64(&state) & mask;
1401 t = size - 1 - v;
1402 if (t <= mask)
1403 {
1404 t = ((t * m) ^ r) & mask;
1405 t = ((t << 1) & mask) | (t >> (masklen - 1));
1406 v = size - 1 - t;
1407 }
1408
1409 /* Random offset */
1410 r = pg_prng_uint64_range(&state, 0, size - 1);
1411 v = (v + r) % size;
1412 }
1413
1414 return (int64) v;
1415}
1416
1417/*
1418 * Initialize the given SimpleStats struct to all zeroes
1419 */
1420static void
1422{
1423 memset(ss, 0, sizeof(SimpleStats));
1424}
1425
1426/*
1427 * Accumulate one value into a SimpleStats struct.
1428 */
1429static void
1430addToSimpleStats(SimpleStats *ss, double val)
1431{
1432 if (ss->count == 0 || val < ss->min)
1433 ss->min = val;
1434 if (ss->count == 0 || val > ss->max)
1435 ss->max = val;
1436 ss->count++;
1437 ss->sum += val;
1438 ss->sum2 += val * val;
1439}
1440
1441/*
1442 * Merge two SimpleStats objects
1443 */
1444static void
1446{
1447 if (acc->count == 0 || ss->min < acc->min)
1448 acc->min = ss->min;
1449 if (acc->count == 0 || ss->max > acc->max)
1450 acc->max = ss->max;
1451 acc->count += ss->count;
1452 acc->sum += ss->sum;
1453 acc->sum2 += ss->sum2;
1454}
1455
1456/*
1457 * Initialize a StatsData struct to mostly zeroes, with its start time set to
1458 * the given value.
1459 */
1460static void
1462{
1463 sd->start_time = start;
1464 sd->cnt = 0;
1465 sd->skipped = 0;
1466 sd->retries = 0;
1467 sd->retried = 0;
1468 sd->serialization_failures = 0;
1469 sd->deadlock_failures = 0;
1471 initSimpleStats(&sd->lag);
1472}
1473
1474/*
1475 * Accumulate one additional item into the given stats object.
1476 */
1477static void
1478accumStats(StatsData *stats, bool skipped, double lat, double lag,
1479 EStatus estatus, int64 tries)
1480{
1481 /* Record the skipped transaction */
1482 if (skipped)
1483 {
1484 /* no latency to record on skipped transactions */
1485 stats->skipped++;
1486 return;
1487 }
1488
1489 /*
1490 * Record the number of retries regardless of whether the transaction was
1491 * successful or failed.
1492 */
1493 if (tries > 1)
1494 {
1495 stats->retries += (tries - 1);
1496 stats->retried++;
1497 }
1498
1499 switch (estatus)
1500 {
1501 /* Record the successful transaction */
1502 case ESTATUS_NO_ERROR:
1503 stats->cnt++;
1504
1505 addToSimpleStats(&stats->latency, lat);
1506
1507 /* and possibly the same for schedule lag */
1508 if (throttle_delay)
1509 addToSimpleStats(&stats->lag, lag);
1510 break;
1511
1512 /* Record the failed transaction */
1514 stats->serialization_failures++;
1515 break;
1517 stats->deadlock_failures++;
1518 break;
1519 default:
1520 /* internal error which should never occur */
1521 pg_fatal("unexpected error status: %d", estatus);
1522 }
1523}
1524
1525/* call PQexec() and exit() on failure */
1526static void
1527executeStatement(PGconn *con, const char *sql)
1528{
1529 PGresult *res;
1530
1531 res = PQexec(con, sql);
1532 if (PQresultStatus(res) != PGRES_COMMAND_OK)
1533 {
1534 pg_log_error("query failed: %s", PQerrorMessage(con));
1535 pg_log_error_detail("Query was: %s", sql);
1536 exit(1);
1537 }
1538 PQclear(res);
1539}
1540
1541/* call PQexec() and complain, but without exiting, on failure */
1542static void
1543tryExecuteStatement(PGconn *con, const char *sql)
1544{
1545 PGresult *res;
1546
1547 res = PQexec(con, sql);
1548 if (PQresultStatus(res) != PGRES_COMMAND_OK)
1549 {
1550 pg_log_error("%s", PQerrorMessage(con));
1551 pg_log_error_detail("(ignoring this error and continuing anyway)");
1552 }
1553 PQclear(res);
1554}
1555
1556/* set up a connection to the backend */
1557static PGconn *
1558doConnect(void)
1559{
1560 PGconn *conn;
1561 bool new_pass;
1562 static char *password = NULL;
1563
1564 /*
1565 * Start the connection. Loop until we have a password if requested by
1566 * backend.
1567 */
1568 do
1569 {
1570#define PARAMS_ARRAY_SIZE 7
1571
1572 const char *keywords[PARAMS_ARRAY_SIZE];
1573 const char *values[PARAMS_ARRAY_SIZE];
1574
1575 keywords[0] = "host";
1576 values[0] = pghost;
1577 keywords[1] = "port";
1578 values[1] = pgport;
1579 keywords[2] = "user";
1580 values[2] = username;
1581 keywords[3] = "password";
1582 values[3] = password;
1583 keywords[4] = "dbname";
1584 values[4] = dbName;
1585 keywords[5] = "fallback_application_name";
1586 values[5] = progname;
1587 keywords[6] = NULL;
1588 values[6] = NULL;
1589
1590 new_pass = false;
1591
1593
1594 if (!conn)
1595 {
1596 pg_log_error("connection to database \"%s\" failed", dbName);
1597 return NULL;
1598 }
1599
1600 if (PQstatus(conn) == CONNECTION_BAD &&
1602 !password)
1603 {
1604 PQfinish(conn);
1605 password = simple_prompt("Password: ", false);
1606 new_pass = true;
1607 }
1608 } while (new_pass);
1609
1610 /* check to see that the backend connection was successfully made */
1612 {
1614 PQfinish(conn);
1615 return NULL;
1616 }
1617
1618 return conn;
1619}
1620
1621/* qsort comparator for Variable array */
1622static int
1623compareVariableNames(const void *v1, const void *v2)
1624{
1625 return strcmp(((const Variable *) v1)->name,
1626 ((const Variable *) v2)->name);
1627}
1628
1629/* Locate a variable by name; returns NULL if unknown */
1630static Variable *
1631lookupVariable(Variables *variables, char *name)
1632{
1633 Variable key;
1634
1635 /* On some versions of Solaris, bsearch of zero items dumps core */
1636 if (variables->nvars <= 0)
1637 return NULL;
1638
1639 /* Sort if we have to */
1640 if (!variables->vars_sorted)
1641 {
1642 qsort(variables->vars, variables->nvars, sizeof(Variable),
1644 variables->vars_sorted = true;
1645 }
1646
1647 /* Now we can search */
1648 key.name = name;
1649 return (Variable *) bsearch(&key,
1650 variables->vars,
1651 variables->nvars,
1652 sizeof(Variable),
1654}
1655
1656/* Get the value of a variable, in string form; returns NULL if unknown */
1657static char *
1658getVariable(Variables *variables, char *name)
1659{
1660 Variable *var;
1661 char stringform[64];
1662
1663 var = lookupVariable(variables, name);
1664 if (var == NULL)
1665 return NULL; /* not found */
1666
1667 if (var->svalue)
1668 return var->svalue; /* we have it in string form */
1669
1670 /* We need to produce a string equivalent of the value */
1671 Assert(var->value.type != PGBT_NO_VALUE);
1672 if (var->value.type == PGBT_NULL)
1673 snprintf(stringform, sizeof(stringform), "NULL");
1674 else if (var->value.type == PGBT_BOOLEAN)
1675 snprintf(stringform, sizeof(stringform),
1676 "%s", var->value.u.bval ? "true" : "false");
1677 else if (var->value.type == PGBT_INT)
1678 snprintf(stringform, sizeof(stringform),
1679 INT64_FORMAT, var->value.u.ival);
1680 else if (var->value.type == PGBT_DOUBLE)
1681 snprintf(stringform, sizeof(stringform),
1682 "%.*g", DBL_DIG, var->value.u.dval);
1683 else /* internal error, unexpected type */
1684 Assert(0);
1685 var->svalue = pg_strdup(stringform);
1686 return var->svalue;
1687}
1688
1689/* Try to convert variable to a value; return false on failure */
1690static bool
1692{
1693 size_t slen;
1694
1695 if (var->value.type != PGBT_NO_VALUE)
1696 return true; /* no work */
1697
1698 slen = strlen(var->svalue);
1699
1700 if (slen == 0)
1701 /* what should it do on ""? */
1702 return false;
1703
1704 if (pg_strcasecmp(var->svalue, "null") == 0)
1705 {
1706 setNullValue(&var->value);
1707 }
1708
1709 /*
1710 * accept prefixes such as y, ye, n, no... but not for "o". 0/1 are
1711 * recognized later as an int, which is converted to bool if needed.
1712 */
1713 else if (pg_strncasecmp(var->svalue, "true", slen) == 0 ||
1714 pg_strncasecmp(var->svalue, "yes", slen) == 0 ||
1715 pg_strcasecmp(var->svalue, "on") == 0)
1716 {
1717 setBoolValue(&var->value, true);
1718 }
1719 else if (pg_strncasecmp(var->svalue, "false", slen) == 0 ||
1720 pg_strncasecmp(var->svalue, "no", slen) == 0 ||
1721 pg_strcasecmp(var->svalue, "off") == 0 ||
1722 pg_strcasecmp(var->svalue, "of") == 0)
1723 {
1724 setBoolValue(&var->value, false);
1725 }
1726 else if (is_an_int(var->svalue))
1727 {
1728 /* if it looks like an int, it must be an int without overflow */
1729 int64 iv;
1730
1731 if (!strtoint64(var->svalue, false, &iv))
1732 return false;
1733
1734 setIntValue(&var->value, iv);
1735 }
1736 else /* type should be double */
1737 {
1738 double dv;
1739
1740 if (!strtodouble(var->svalue, true, &dv))
1741 {
1742 pg_log_error("malformed variable \"%s\" value: \"%s\"",
1743 var->name, var->svalue);
1744 return false;
1745 }
1746 setDoubleValue(&var->value, dv);
1747 }
1748 return true;
1749}
1750
1751/*
1752 * Check whether a variable's name is allowed.
1753 *
1754 * We allow any non-ASCII character, as well as ASCII letters, digits, and
1755 * underscore.
1756 *
1757 * Keep this in sync with the definitions of variable name characters in
1758 * "src/fe_utils/psqlscan.l", "src/bin/psql/psqlscanslash.l" and
1759 * "src/bin/pgbench/exprscan.l". Also see parseVariable(), below.
1760 *
1761 * Note: this static function is copied from "src/bin/psql/variables.c"
1762 * but changed to disallow variable names starting with a digit.
1763 */
1764static bool
1765valid_variable_name(const char *name)
1766{
1767 const unsigned char *ptr = (const unsigned char *) name;
1768
1769 /* Mustn't be zero-length */
1770 if (*ptr == '\0')
1771 return false;
1772
1773 /* must not start with [0-9] */
1774 if (IS_HIGHBIT_SET(*ptr) ||
1775 strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1776 "_", *ptr) != NULL)
1777 ptr++;
1778 else
1779 return false;
1780
1781 /* remaining characters can include [0-9] */
1782 while (*ptr)
1783 {
1784 if (IS_HIGHBIT_SET(*ptr) ||
1785 strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1786 "_0123456789", *ptr) != NULL)
1787 ptr++;
1788 else
1789 return false;
1790 }
1791
1792 return true;
1793}
1794
1795/*
1796 * Make sure there is enough space for 'needed' more variable in the variables
1797 * array.
1798 */
1799static void
1800enlargeVariables(Variables *variables, int needed)
1801{
1802 /* total number of variables required now */
1803 needed += variables->nvars;
1804
1805 if (variables->max_vars < needed)
1806 {
1807 variables->max_vars = needed + VARIABLES_ALLOC_MARGIN;
1808 variables->vars = (Variable *)
1809 pg_realloc(variables->vars, variables->max_vars * sizeof(Variable));
1810 }
1811}
1812
1813/*
1814 * Lookup a variable by name, creating it if need be.
1815 * Caller is expected to assign a value to the variable.
1816 * Returns NULL on failure (bad name).
1817 */
1818static Variable *
1819lookupCreateVariable(Variables *variables, const char *context, char *name)
1820{
1821 Variable *var;
1822
1823 var = lookupVariable(variables, name);
1824 if (var == NULL)
1825 {
1826 /*
1827 * Check for the name only when declaring a new variable to avoid
1828 * overhead.
1829 */
1831 {
1832 pg_log_error("%s: invalid variable name: \"%s\"", context, name);
1833 return NULL;
1834 }
1835
1836 /* Create variable at the end of the array */
1837 enlargeVariables(variables, 1);
1838
1839 var = &(variables->vars[variables->nvars]);
1840
1841 var->name = pg_strdup(name);
1842 var->svalue = NULL;
1843 /* caller is expected to initialize remaining fields */
1844
1845 variables->nvars++;
1846 /* we don't re-sort the array till we have to */
1847 variables->vars_sorted = false;
1848 }
1849
1850 return var;
1851}
1852
1853/* Assign a string value to a variable, creating it if need be */
1854/* Returns false on failure (bad name) */
1855static bool
1856putVariable(Variables *variables, const char *context, char *name,
1857 const char *value)
1858{
1859 Variable *var;
1860 char *val;
1861
1862 var = lookupCreateVariable(variables, context, name);
1863 if (!var)
1864 return false;
1865
1866 /* dup then free, in case value is pointing at this variable */
1867 val = pg_strdup(value);
1868
1869 free(var->svalue);
1870 var->svalue = val;
1871 var->value.type = PGBT_NO_VALUE;
1872
1873 return true;
1874}
1875
1876/* Assign a value to a variable, creating it if need be */
1877/* Returns false on failure (bad name) */
1878static bool
1879putVariableValue(Variables *variables, const char *context, char *name,
1880 const PgBenchValue *value)
1881{
1882 Variable *var;
1883
1884 var = lookupCreateVariable(variables, context, name);
1885 if (!var)
1886 return false;
1887
1888 free(var->svalue);
1889 var->svalue = NULL;
1890 var->value = *value;
1891
1892 return true;
1893}
1894
1895/* Assign an integer value to a variable, creating it if need be */
1896/* Returns false on failure (bad name) */
1897static bool
1898putVariableInt(Variables *variables, const char *context, char *name,
1899 int64 value)
1900{
1902
1904 return putVariableValue(variables, context, name, &val);
1905}
1906
1907/*
1908 * Parse a possible variable reference (:varname).
1909 *
1910 * "sql" points at a colon. If what follows it looks like a valid
1911 * variable name, return a malloc'd string containing the variable name,
1912 * and set *eaten to the number of characters consumed (including the colon).
1913 * Otherwise, return NULL.
1914 */
1915static char *
1916parseVariable(const char *sql, int *eaten)
1917{
1918 int i = 1; /* starting at 1 skips the colon */
1919 char *name;
1920
1921 /* keep this logic in sync with valid_variable_name() */
1922 if (IS_HIGHBIT_SET(sql[i]) ||
1923 strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1924 "_", sql[i]) != NULL)
1925 i++;
1926 else
1927 return NULL;
1928
1929 while (IS_HIGHBIT_SET(sql[i]) ||
1930 strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
1931 "_0123456789", sql[i]) != NULL)
1932 i++;
1933
1934 name = pg_malloc(i);
1935 memcpy(name, &sql[1], i - 1);
1936 name[i - 1] = '\0';
1937
1938 *eaten = i;
1939 return name;
1940}
1941
1942static char *
1943replaceVariable(char **sql, char *param, int len, char *value)
1944{
1945 int valueln = strlen(value);
1946
1947 if (valueln > len)
1948 {
1949 size_t offset = param - *sql;
1950
1951 *sql = pg_realloc(*sql, strlen(*sql) - len + valueln + 1);
1952 param = *sql + offset;
1953 }
1954
1955 if (valueln != len)
1956 memmove(param + valueln, param + len, strlen(param + len) + 1);
1957 memcpy(param, value, valueln);
1958
1959 return param + valueln;
1960}
1961
1962static char *
1963assignVariables(Variables *variables, char *sql)
1964{
1965 char *p,
1966 *name,
1967 *val;
1968
1969 p = sql;
1970 while ((p = strchr(p, ':')) != NULL)
1971 {
1972 int eaten;
1973
1974 name = parseVariable(p, &eaten);
1975 if (name == NULL)
1976 {
1977 while (*p == ':')
1978 {
1979 p++;
1980 }
1981 continue;
1982 }
1983
1984 val = getVariable(variables, name);
1985 free(name);
1986 if (val == NULL)
1987 {
1988 p++;
1989 continue;
1990 }
1991
1992 p = replaceVariable(&sql, p, eaten, val);
1993 }
1994
1995 return sql;
1996}
1997
1998static void
1999getQueryParams(Variables *variables, const Command *command,
2000 const char **params)
2001{
2002 int i;
2003
2004 for (i = 0; i < command->argc - 1; i++)
2005 params[i] = getVariable(variables, command->argv[i + 1]);
2006}
2007
2008static char *
2010{
2011 if (pval->type == PGBT_NO_VALUE)
2012 return "none";
2013 else if (pval->type == PGBT_NULL)
2014 return "null";
2015 else if (pval->type == PGBT_INT)
2016 return "int";
2017 else if (pval->type == PGBT_DOUBLE)
2018 return "double";
2019 else if (pval->type == PGBT_BOOLEAN)
2020 return "boolean";
2021 else
2022 {
2023 /* internal error, should never get there */
2024 Assert(false);
2025 return NULL;
2026 }
2027}
2028
2029/* get a value as a boolean, or tell if there is a problem */
2030static bool
2031coerceToBool(PgBenchValue *pval, bool *bval)
2032{
2033 if (pval->type == PGBT_BOOLEAN)
2034 {
2035 *bval = pval->u.bval;
2036 return true;
2037 }
2038 else /* NULL, INT or DOUBLE */
2039 {
2040 pg_log_error("cannot coerce %s to boolean", valueTypeName(pval));
2041 *bval = false; /* suppress uninitialized-variable warnings */
2042 return false;
2043 }
2044}
2045
2046/*
2047 * Return true or false from an expression for conditional purposes.
2048 * Non zero numerical values are true, zero and NULL are false.
2049 */
2050static bool
2052{
2053 switch (pval->type)
2054 {
2055 case PGBT_NULL:
2056 return false;
2057 case PGBT_BOOLEAN:
2058 return pval->u.bval;
2059 case PGBT_INT:
2060 return pval->u.ival != 0;
2061 case PGBT_DOUBLE:
2062 return pval->u.dval != 0.0;
2063 default:
2064 /* internal error, unexpected type */
2065 Assert(0);
2066 return false;
2067 }
2068}
2069
2070/* get a value as an int, tell if there is a problem */
2071static bool
2072coerceToInt(PgBenchValue *pval, int64 *ival)
2073{
2074 if (pval->type == PGBT_INT)
2075 {
2076 *ival = pval->u.ival;
2077 return true;
2078 }
2079 else if (pval->type == PGBT_DOUBLE)
2080 {
2081 double dval = rint(pval->u.dval);
2082
2083 if (isnan(dval) || !FLOAT8_FITS_IN_INT64(dval))
2084 {
2085 pg_log_error("double to int overflow for %f", dval);
2086 return false;
2087 }
2088 *ival = (int64) dval;
2089 return true;
2090 }
2091 else /* BOOLEAN or NULL */
2092 {
2093 pg_log_error("cannot coerce %s to int", valueTypeName(pval));
2094 return false;
2095 }
2096}
2097
2098/* get a value as a double, or tell if there is a problem */
2099static bool
2100coerceToDouble(PgBenchValue *pval, double *dval)
2101{
2102 if (pval->type == PGBT_DOUBLE)
2103 {
2104 *dval = pval->u.dval;
2105 return true;
2106 }
2107 else if (pval->type == PGBT_INT)
2108 {
2109 *dval = (double) pval->u.ival;
2110 return true;
2111 }
2112 else /* BOOLEAN or NULL */
2113 {
2114 pg_log_error("cannot coerce %s to double", valueTypeName(pval));
2115 return false;
2116 }
2117}
2118
2119/* assign a null value */
2120static void
2122{
2123 pv->type = PGBT_NULL;
2124 pv->u.ival = 0;
2125}
2126
2127/* assign a boolean value */
2128static void
2129setBoolValue(PgBenchValue *pv, bool bval)
2130{
2131 pv->type = PGBT_BOOLEAN;
2132 pv->u.bval = bval;
2133}
2134
2135/* assign an integer value */
2136static void
2138{
2139 pv->type = PGBT_INT;
2140 pv->u.ival = ival;
2141}
2142
2143/* assign a double value */
2144static void
2145setDoubleValue(PgBenchValue *pv, double dval)
2146{
2147 pv->type = PGBT_DOUBLE;
2148 pv->u.dval = dval;
2149}
2150
2151static bool
2153{
2154 return func == PGBENCH_AND || func == PGBENCH_OR || func == PGBENCH_CASE;
2155}
2156
2157/* lazy evaluation of some functions */
2158static bool
2161{
2163 a2;
2164 bool ba1,
2165 ba2;
2166
2167 Assert(isLazyFunc(func) && args != NULL && args->next != NULL);
2168
2169 /* args points to first condition */
2170 if (!evaluateExpr(st, args->expr, &a1))
2171 return false;
2172
2173 /* second condition for AND/OR and corresponding branch for CASE */
2174 args = args->next;
2175
2176 switch (func)
2177 {
2178 case PGBENCH_AND:
2179 if (a1.type == PGBT_NULL)
2180 {
2181 setNullValue(retval);
2182 return true;
2183 }
2184
2185 if (!coerceToBool(&a1, &ba1))
2186 return false;
2187
2188 if (!ba1)
2189 {
2190 setBoolValue(retval, false);
2191 return true;
2192 }
2193
2194 if (!evaluateExpr(st, args->expr, &a2))
2195 return false;
2196
2197 if (a2.type == PGBT_NULL)
2198 {
2199 setNullValue(retval);
2200 return true;
2201 }
2202 else if (!coerceToBool(&a2, &ba2))
2203 return false;
2204 else
2205 {
2206 setBoolValue(retval, ba2);
2207 return true;
2208 }
2209
2210 return true;
2211
2212 case PGBENCH_OR:
2213
2214 if (a1.type == PGBT_NULL)
2215 {
2216 setNullValue(retval);
2217 return true;
2218 }
2219
2220 if (!coerceToBool(&a1, &ba1))
2221 return false;
2222
2223 if (ba1)
2224 {
2225 setBoolValue(retval, true);
2226 return true;
2227 }
2228
2229 if (!evaluateExpr(st, args->expr, &a2))
2230 return false;
2231
2232 if (a2.type == PGBT_NULL)
2233 {
2234 setNullValue(retval);
2235 return true;
2236 }
2237 else if (!coerceToBool(&a2, &ba2))
2238 return false;
2239 else
2240 {
2241 setBoolValue(retval, ba2);
2242 return true;
2243 }
2244
2245 case PGBENCH_CASE:
2246 /* when true, execute branch */
2247 if (valueTruth(&a1))
2248 return evaluateExpr(st, args->expr, retval);
2249
2250 /* now args contains next condition or final else expression */
2251 args = args->next;
2252
2253 /* final else case? */
2254 if (args->next == NULL)
2255 return evaluateExpr(st, args->expr, retval);
2256
2257 /* no, another when, proceed */
2258 return evalLazyFunc(st, PGBENCH_CASE, args, retval);
2259
2260 default:
2261 /* internal error, cannot get here */
2262 Assert(0);
2263 break;
2264 }
2265 return false;
2266}
2267
2268/* maximum number of function arguments */
2269#define MAX_FARGS 16
2270
2271/*
2272 * Recursive evaluation of standard functions,
2273 * which do not require lazy evaluation.
2274 */
2275static bool
2278 PgBenchValue *retval)
2279{
2280 /* evaluate all function arguments */
2281 int nargs = 0;
2282 PgBenchValue vargs[MAX_FARGS] = {0};
2283 PgBenchExprLink *l = args;
2284 bool has_null = false;
2285
2286 for (nargs = 0; nargs < MAX_FARGS && l != NULL; nargs++, l = l->next)
2287 {
2288 if (!evaluateExpr(st, l->expr, &vargs[nargs]))
2289 return false;
2290 has_null |= vargs[nargs].type == PGBT_NULL;
2291 }
2292
2293 if (l != NULL)
2294 {
2295 pg_log_error("too many function arguments, maximum is %d", MAX_FARGS);
2296 return false;
2297 }
2298
2299 /* NULL arguments */
2300 if (has_null && func != PGBENCH_IS && func != PGBENCH_DEBUG)
2301 {
2302 setNullValue(retval);
2303 return true;
2304 }
2305
2306 /* then evaluate function */
2307 switch (func)
2308 {
2309 /* overloaded operators */
2310 case PGBENCH_ADD:
2311 case PGBENCH_SUB:
2312 case PGBENCH_MUL:
2313 case PGBENCH_DIV:
2314 case PGBENCH_MOD:
2315 case PGBENCH_EQ:
2316 case PGBENCH_NE:
2317 case PGBENCH_LE:
2318 case PGBENCH_LT:
2319 {
2320 PgBenchValue *lval = &vargs[0],
2321 *rval = &vargs[1];
2322
2323 Assert(nargs == 2);
2324
2325 /* overloaded type management, double if some double */
2326 if ((lval->type == PGBT_DOUBLE ||
2327 rval->type == PGBT_DOUBLE) && func != PGBENCH_MOD)
2328 {
2329 double ld,
2330 rd;
2331
2332 if (!coerceToDouble(lval, &ld) ||
2333 !coerceToDouble(rval, &rd))
2334 return false;
2335
2336 switch (func)
2337 {
2338 case PGBENCH_ADD:
2339 setDoubleValue(retval, ld + rd);
2340 return true;
2341
2342 case PGBENCH_SUB:
2343 setDoubleValue(retval, ld - rd);
2344 return true;
2345
2346 case PGBENCH_MUL:
2347 setDoubleValue(retval, ld * rd);
2348 return true;
2349
2350 case PGBENCH_DIV:
2351 setDoubleValue(retval, ld / rd);
2352 return true;
2353
2354 case PGBENCH_EQ:
2355 setBoolValue(retval, ld == rd);
2356 return true;
2357
2358 case PGBENCH_NE:
2359 setBoolValue(retval, ld != rd);
2360 return true;
2361
2362 case PGBENCH_LE:
2363 setBoolValue(retval, ld <= rd);
2364 return true;
2365
2366 case PGBENCH_LT:
2367 setBoolValue(retval, ld < rd);
2368 return true;
2369
2370 default:
2371 /* cannot get here */
2372 Assert(0);
2373 }
2374 }
2375 else /* we have integer operands, or % */
2376 {
2377 int64 li,
2378 ri,
2379 res;
2380
2381 if (!coerceToInt(lval, &li) ||
2382 !coerceToInt(rval, &ri))
2383 return false;
2384
2385 switch (func)
2386 {
2387 case PGBENCH_ADD:
2388 if (pg_add_s64_overflow(li, ri, &res))
2389 {
2390 pg_log_error("bigint add out of range");
2391 return false;
2392 }
2393 setIntValue(retval, res);
2394 return true;
2395
2396 case PGBENCH_SUB:
2397 if (pg_sub_s64_overflow(li, ri, &res))
2398 {
2399 pg_log_error("bigint sub out of range");
2400 return false;
2401 }
2402 setIntValue(retval, res);
2403 return true;
2404
2405 case PGBENCH_MUL:
2406 if (pg_mul_s64_overflow(li, ri, &res))
2407 {
2408 pg_log_error("bigint mul out of range");
2409 return false;
2410 }
2411 setIntValue(retval, res);
2412 return true;
2413
2414 case PGBENCH_EQ:
2415 setBoolValue(retval, li == ri);
2416 return true;
2417
2418 case PGBENCH_NE:
2419 setBoolValue(retval, li != ri);
2420 return true;
2421
2422 case PGBENCH_LE:
2423 setBoolValue(retval, li <= ri);
2424 return true;
2425
2426 case PGBENCH_LT:
2427 setBoolValue(retval, li < ri);
2428 return true;
2429
2430 case PGBENCH_DIV:
2431 case PGBENCH_MOD:
2432 if (ri == 0)
2433 {
2434 pg_log_error("division by zero");
2435 return false;
2436 }
2437 /* special handling of -1 divisor */
2438 if (ri == -1)
2439 {
2440 if (func == PGBENCH_DIV)
2441 {
2442 /* overflow check (needed for INT64_MIN) */
2443 if (li == PG_INT64_MIN)
2444 {
2445 pg_log_error("bigint div out of range");
2446 return false;
2447 }
2448 else
2449 setIntValue(retval, -li);
2450 }
2451 else
2452 setIntValue(retval, 0);
2453 return true;
2454 }
2455 /* else divisor is not -1 */
2456 if (func == PGBENCH_DIV)
2457 setIntValue(retval, li / ri);
2458 else /* func == PGBENCH_MOD */
2459 setIntValue(retval, li % ri);
2460
2461 return true;
2462
2463 default:
2464 /* cannot get here */
2465 Assert(0);
2466 }
2467 }
2468
2469 Assert(0);
2470 return false; /* NOTREACHED */
2471 }
2472
2473 /* integer bitwise operators */
2474 case PGBENCH_BITAND:
2475 case PGBENCH_BITOR:
2476 case PGBENCH_BITXOR:
2477 case PGBENCH_LSHIFT:
2478 case PGBENCH_RSHIFT:
2479 {
2480 int64 li,
2481 ri;
2482
2483 if (!coerceToInt(&vargs[0], &li) || !coerceToInt(&vargs[1], &ri))
2484 return false;
2485
2486 if (func == PGBENCH_BITAND)
2487 setIntValue(retval, li & ri);
2488 else if (func == PGBENCH_BITOR)
2489 setIntValue(retval, li | ri);
2490 else if (func == PGBENCH_BITXOR)
2491 setIntValue(retval, li ^ ri);
2492 else if (func == PGBENCH_LSHIFT)
2493 setIntValue(retval, li << ri);
2494 else if (func == PGBENCH_RSHIFT)
2495 setIntValue(retval, li >> ri);
2496 else /* cannot get here */
2497 Assert(0);
2498
2499 return true;
2500 }
2501
2502 /* logical operators */
2503 case PGBENCH_NOT:
2504 {
2505 bool b;
2506
2507 if (!coerceToBool(&vargs[0], &b))
2508 return false;
2509
2510 setBoolValue(retval, !b);
2511 return true;
2512 }
2513
2514 /* no arguments */
2515 case PGBENCH_PI:
2516 setDoubleValue(retval, M_PI);
2517 return true;
2518
2519 /* 1 overloaded argument */
2520 case PGBENCH_ABS:
2521 {
2522 PgBenchValue *varg = &vargs[0];
2523
2524 Assert(nargs == 1);
2525
2526 if (varg->type == PGBT_INT)
2527 {
2528 int64 i = varg->u.ival;
2529
2530 setIntValue(retval, i < 0 ? -i : i);
2531 }
2532 else
2533 {
2534 double d = varg->u.dval;
2535
2536 Assert(varg->type == PGBT_DOUBLE);
2537 setDoubleValue(retval, d < 0.0 ? -d : d);
2538 }
2539
2540 return true;
2541 }
2542
2543 case PGBENCH_DEBUG:
2544 {
2545 PgBenchValue *varg = &vargs[0];
2546
2547 Assert(nargs == 1);
2548
2549 fprintf(stderr, "debug(script=%d,command=%d): ",
2550 st->use_file, st->command + 1);
2551
2552 if (varg->type == PGBT_NULL)
2553 fprintf(stderr, "null\n");
2554 else if (varg->type == PGBT_BOOLEAN)
2555 fprintf(stderr, "boolean %s\n", varg->u.bval ? "true" : "false");
2556 else if (varg->type == PGBT_INT)
2557 fprintf(stderr, "int " INT64_FORMAT "\n", varg->u.ival);
2558 else if (varg->type == PGBT_DOUBLE)
2559 fprintf(stderr, "double %.*g\n", DBL_DIG, varg->u.dval);
2560 else /* internal error, unexpected type */
2561 Assert(0);
2562
2563 *retval = *varg;
2564
2565 return true;
2566 }
2567
2568 /* 1 double argument */
2569 case PGBENCH_DOUBLE:
2570 case PGBENCH_SQRT:
2571 case PGBENCH_LN:
2572 case PGBENCH_EXP:
2573 {
2574 double dval;
2575
2576 Assert(nargs == 1);
2577
2578 if (!coerceToDouble(&vargs[0], &dval))
2579 return false;
2580
2581 if (func == PGBENCH_SQRT)
2582 dval = sqrt(dval);
2583 else if (func == PGBENCH_LN)
2584 dval = log(dval);
2585 else if (func == PGBENCH_EXP)
2586 dval = exp(dval);
2587 /* else is cast: do nothing */
2588
2589 setDoubleValue(retval, dval);
2590 return true;
2591 }
2592
2593 /* 1 int argument */
2594 case PGBENCH_INT:
2595 {
2596 int64 ival;
2597
2598 Assert(nargs == 1);
2599
2600 if (!coerceToInt(&vargs[0], &ival))
2601 return false;
2602
2603 setIntValue(retval, ival);
2604 return true;
2605 }
2606
2607 /* variable number of arguments */
2608 case PGBENCH_LEAST:
2609 case PGBENCH_GREATEST:
2610 {
2611 bool havedouble;
2612 int i;
2613
2614 Assert(nargs >= 1);
2615
2616 /* need double result if any input is double */
2617 havedouble = false;
2618 for (i = 0; i < nargs; i++)
2619 {
2620 if (vargs[i].type == PGBT_DOUBLE)
2621 {
2622 havedouble = true;
2623 break;
2624 }
2625 }
2626 if (havedouble)
2627 {
2628 double extremum;
2629
2630 if (!coerceToDouble(&vargs[0], &extremum))
2631 return false;
2632 for (i = 1; i < nargs; i++)
2633 {
2634 double dval;
2635
2636 if (!coerceToDouble(&vargs[i], &dval))
2637 return false;
2638 if (func == PGBENCH_LEAST)
2639 extremum = Min(extremum, dval);
2640 else
2641 extremum = Max(extremum, dval);
2642 }
2643 setDoubleValue(retval, extremum);
2644 }
2645 else
2646 {
2647 int64 extremum;
2648
2649 if (!coerceToInt(&vargs[0], &extremum))
2650 return false;
2651 for (i = 1; i < nargs; i++)
2652 {
2653 int64 ival;
2654
2655 if (!coerceToInt(&vargs[i], &ival))
2656 return false;
2657 if (func == PGBENCH_LEAST)
2658 extremum = Min(extremum, ival);
2659 else
2660 extremum = Max(extremum, ival);
2661 }
2662 setIntValue(retval, extremum);
2663 }
2664 return true;
2665 }
2666
2667 /* random functions */
2668 case PGBENCH_RANDOM:
2672 {
2673 int64 imin,
2674 imax,
2675 delta;
2676
2677 Assert(nargs >= 2);
2678
2679 if (!coerceToInt(&vargs[0], &imin) ||
2680 !coerceToInt(&vargs[1], &imax))
2681 return false;
2682
2683 /* check random range */
2684 if (unlikely(imin > imax))
2685 {
2686 pg_log_error("empty range given to random");
2687 return false;
2688 }
2689 else if (unlikely(pg_sub_s64_overflow(imax, imin, &delta) ||
2690 pg_add_s64_overflow(delta, 1, &delta)))
2691 {
2692 /* prevent int overflows in random functions */
2693 pg_log_error("random range is too large");
2694 return false;
2695 }
2696
2697 if (func == PGBENCH_RANDOM)
2698 {
2699 Assert(nargs == 2);
2700 setIntValue(retval, getrand(&st->cs_func_rs, imin, imax));
2701 }
2702 else /* gaussian & exponential */
2703 {
2704 double param;
2705
2706 Assert(nargs == 3);
2707
2708 if (!coerceToDouble(&vargs[2], &param))
2709 return false;
2710
2711 if (func == PGBENCH_RANDOM_GAUSSIAN)
2712 {
2713 if (param < MIN_GAUSSIAN_PARAM)
2714 {
2715 pg_log_error("gaussian parameter must be at least %f (not %f)",
2716 MIN_GAUSSIAN_PARAM, param);
2717 return false;
2718 }
2719
2720 setIntValue(retval,
2722 imin, imax, param));
2723 }
2724 else if (func == PGBENCH_RANDOM_ZIPFIAN)
2725 {
2726 if (param < MIN_ZIPFIAN_PARAM || param > MAX_ZIPFIAN_PARAM)
2727 {
2728 pg_log_error("zipfian parameter must be in range [%.3f, %.0f] (not %f)",
2730 return false;
2731 }
2732
2733 setIntValue(retval,
2734 getZipfianRand(&st->cs_func_rs, imin, imax, param));
2735 }
2736 else /* exponential */
2737 {
2738 if (param <= 0.0)
2739 {
2740 pg_log_error("exponential parameter must be greater than zero (not %f)",
2741 param);
2742 return false;
2743 }
2744
2745 setIntValue(retval,
2747 imin, imax, param));
2748 }
2749 }
2750
2751 return true;
2752 }
2753
2754 case PGBENCH_POW:
2755 {
2756 PgBenchValue *lval = &vargs[0];
2757 PgBenchValue *rval = &vargs[1];
2758 double ld,
2759 rd;
2760
2761 Assert(nargs == 2);
2762
2763 if (!coerceToDouble(lval, &ld) ||
2764 !coerceToDouble(rval, &rd))
2765 return false;
2766
2767 setDoubleValue(retval, pow(ld, rd));
2768
2769 return true;
2770 }
2771
2772 case PGBENCH_IS:
2773 {
2774 Assert(nargs == 2);
2775
2776 /*
2777 * note: this simple implementation is more permissive than
2778 * SQL
2779 */
2780 setBoolValue(retval,
2781 vargs[0].type == vargs[1].type &&
2782 vargs[0].u.bval == vargs[1].u.bval);
2783 return true;
2784 }
2785
2786 /* hashing */
2787 case PGBENCH_HASH_FNV1A:
2789 {
2790 int64 val,
2791 seed;
2792
2793 Assert(nargs == 2);
2794
2795 if (!coerceToInt(&vargs[0], &val) ||
2796 !coerceToInt(&vargs[1], &seed))
2797 return false;
2798
2799 if (func == PGBENCH_HASH_MURMUR2)
2800 setIntValue(retval, getHashMurmur2(val, seed));
2801 else if (func == PGBENCH_HASH_FNV1A)
2802 setIntValue(retval, getHashFnv1a(val, seed));
2803 else
2804 /* cannot get here */
2805 Assert(0);
2806
2807 return true;
2808 }
2809
2810 case PGBENCH_PERMUTE:
2811 {
2812 int64 val,
2813 size,
2814 seed;
2815
2816 Assert(nargs == 3);
2817
2818 if (!coerceToInt(&vargs[0], &val) ||
2819 !coerceToInt(&vargs[1], &size) ||
2820 !coerceToInt(&vargs[2], &seed))
2821 return false;
2822
2823 if (size <= 0)
2824 {
2825 pg_log_error("permute size parameter must be greater than zero");
2826 return false;
2827 }
2828
2829 setIntValue(retval, permute(val, size, seed));
2830 return true;
2831 }
2832
2833 default:
2834 /* cannot get here */
2835 Assert(0);
2836 /* dead code to avoid a compiler warning */
2837 return false;
2838 }
2839}
2840
2841/* evaluate some function */
2842static bool
2843evalFunc(CState *st,
2845{
2846 if (isLazyFunc(func))
2847 return evalLazyFunc(st, func, args, retval);
2848 else
2849 return evalStandardFunc(st, func, args, retval);
2850}
2851
2852/*
2853 * Recursive evaluation of an expression in a pgbench script
2854 * using the current state of variables.
2855 * Returns whether the evaluation was ok,
2856 * the value itself is returned through the retval pointer.
2857 */
2858static bool
2859evaluateExpr(CState *st, PgBenchExpr *expr, PgBenchValue *retval)
2860{
2861 switch (expr->etype)
2862 {
2863 case ENODE_CONSTANT:
2864 {
2865 *retval = expr->u.constant;
2866 return true;
2867 }
2868
2869 case ENODE_VARIABLE:
2870 {
2871 Variable *var;
2872
2873 if ((var = lookupVariable(&st->variables, expr->u.variable.varname)) == NULL)
2874 {
2875 pg_log_error("undefined variable \"%s\"", expr->u.variable.varname);
2876 return false;
2877 }
2878
2879 if (!makeVariableValue(var))
2880 return false;
2881
2882 *retval = var->value;
2883 return true;
2884 }
2885
2886 case ENODE_FUNCTION:
2887 return evalFunc(st,
2888 expr->u.function.function,
2889 expr->u.function.args,
2890 retval);
2891
2892 default:
2893 /* internal error which should never occur */
2894 pg_fatal("unexpected enode type in evaluation: %d", expr->etype);
2895 }
2896}
2897
2898/*
2899 * Convert command name to meta-command enum identifier
2900 */
2902getMetaCommand(const char *cmd)
2903{
2904 MetaCommand mc;
2905
2906 if (cmd == NULL)
2907 mc = META_NONE;
2908 else if (pg_strcasecmp(cmd, "set") == 0)
2909 mc = META_SET;
2910 else if (pg_strcasecmp(cmd, "setshell") == 0)
2911 mc = META_SETSHELL;
2912 else if (pg_strcasecmp(cmd, "shell") == 0)
2913 mc = META_SHELL;
2914 else if (pg_strcasecmp(cmd, "sleep") == 0)
2915 mc = META_SLEEP;
2916 else if (pg_strcasecmp(cmd, "if") == 0)
2917 mc = META_IF;
2918 else if (pg_strcasecmp(cmd, "elif") == 0)
2919 mc = META_ELIF;
2920 else if (pg_strcasecmp(cmd, "else") == 0)
2921 mc = META_ELSE;
2922 else if (pg_strcasecmp(cmd, "endif") == 0)
2923 mc = META_ENDIF;
2924 else if (pg_strcasecmp(cmd, "gset") == 0)
2925 mc = META_GSET;
2926 else if (pg_strcasecmp(cmd, "aset") == 0)
2927 mc = META_ASET;
2928 else if (pg_strcasecmp(cmd, "startpipeline") == 0)
2929 mc = META_STARTPIPELINE;
2930 else if (pg_strcasecmp(cmd, "syncpipeline") == 0)
2931 mc = META_SYNCPIPELINE;
2932 else if (pg_strcasecmp(cmd, "endpipeline") == 0)
2933 mc = META_ENDPIPELINE;
2934 else
2935 mc = META_NONE;
2936 return mc;
2937}
2938
2939/*
2940 * Run a shell command. The result is assigned to the variable if not NULL.
2941 * Return true if succeeded, or false on error.
2942 */
2943static bool
2944runShellCommand(Variables *variables, char *variable, char **argv, int argc)
2945{
2946 char command[SHELL_COMMAND_SIZE];
2947 int i,
2948 len = 0;
2949 FILE *fp;
2950 char res[64];
2951 char *endptr;
2952 int retval;
2953
2954 /*----------
2955 * Join arguments with whitespace separators. Arguments starting with
2956 * exactly one colon are treated as variables:
2957 * name - append a string "name"
2958 * :var - append a variable named 'var'
2959 * ::name - append a string ":name"
2960 *----------
2961 */
2962 for (i = 0; i < argc; i++)
2963 {
2964 char *arg;
2965 int arglen;
2966
2967 if (argv[i][0] != ':')
2968 {
2969 arg = argv[i]; /* a string literal */
2970 }
2971 else if (argv[i][1] == ':')
2972 {
2973 arg = argv[i] + 1; /* a string literal starting with colons */
2974 }
2975 else if ((arg = getVariable(variables, argv[i] + 1)) == NULL)
2976 {
2977 pg_log_error("%s: undefined variable \"%s\"", argv[0], argv[i]);
2978 return false;
2979 }
2980
2981 arglen = strlen(arg);
2982 if (len + arglen + (i > 0 ? 1 : 0) >= SHELL_COMMAND_SIZE - 1)
2983 {
2984 pg_log_error("%s: shell command is too long", argv[0]);
2985 return false;
2986 }
2987
2988 if (i > 0)
2989 command[len++] = ' ';
2990 memcpy(command + len, arg, arglen);
2991 len += arglen;
2992 }
2993
2994 command[len] = '\0';
2995
2996 fflush(NULL); /* needed before either system() or popen() */
2997
2998 /* Fast path for non-assignment case */
2999 if (variable == NULL)
3000 {
3001 if (system(command))
3002 {
3003 if (!timer_exceeded)
3004 pg_log_error("%s: could not launch shell command", argv[0]);
3005 return false;
3006 }
3007 return true;
3008 }
3009
3010 /* Execute the command with pipe and read the standard output. */
3011 if ((fp = popen(command, "r")) == NULL)
3012 {
3013 pg_log_error("%s: could not launch shell command", argv[0]);
3014 return false;
3015 }
3016 if (fgets(res, sizeof(res), fp) == NULL)
3017 {
3018 if (!timer_exceeded)
3019 pg_log_error("%s: could not read result of shell command", argv[0]);
3020 (void) pclose(fp);
3021 return false;
3022 }
3023 if (pclose(fp) < 0)
3024 {
3025 pg_log_error("%s: could not run shell command: %m", argv[0]);
3026 return false;
3027 }
3028
3029 /* Check whether the result is an integer and assign it to the variable */
3030 retval = (int) strtol(res, &endptr, 10);
3031 while (*endptr != '\0' && isspace((unsigned char) *endptr))
3032 endptr++;
3033 if (*res == '\0' || *endptr != '\0')
3034 {
3035 pg_log_error("%s: shell command must return an integer (not \"%s\")", argv[0], res);
3036 return false;
3037 }
3038 if (!putVariableInt(variables, "setshell", variable, retval))
3039 return false;
3040
3041 pg_log_debug("%s: shell parameter name: \"%s\", value: \"%s\"", argv[0], argv[1], res);
3042
3043 return true;
3044}
3045
3046/*
3047 * Report the abortion of the client when processing SQL commands.
3048 */
3049static void
3050commandFailed(CState *st, const char *cmd, const char *message)
3051{
3052 pg_log_error("client %d aborted in command %d (%s) of script %d; %s",
3053 st->id, st->command, cmd, st->use_file, message);
3054}
3055
3056/*
3057 * Report the error in the command while the script is executing.
3058 */
3059static void
3060commandError(CState *st, const char *message)
3061{
3063 pg_log_info("client %d got an error in command %d (SQL) of script %d; %s",
3064 st->id, st->command, st->use_file, message);
3065}
3066
3067/* return a script number with a weighted choice. */
3068static int
3069chooseScript(TState *thread)
3070{
3071 int i = 0;
3072 int64 w;
3073
3074 if (num_scripts == 1)
3075 return 0;
3076
3077 w = getrand(&thread->ts_choose_rs, 0, total_weight - 1);
3078 do
3079 {
3080 w -= sql_script[i++].weight;
3081 } while (w >= 0);
3082
3083 return i - 1;
3084}
3085
3086/*
3087 * Allocate space for CState->prepared: we need one boolean for each command
3088 * of each script.
3089 */
3090static void
3092{
3093 Assert(st->prepared == NULL);
3094
3095 st->prepared = pg_malloc(sizeof(bool *) * num_scripts);
3096 for (int i = 0; i < num_scripts; i++)
3097 {
3098 ParsedScript *script = &sql_script[i];
3099 int numcmds;
3100
3101 for (numcmds = 0; script->commands[numcmds] != NULL; numcmds++)
3102 ;
3103 st->prepared[i] = pg_malloc0(sizeof(bool) * numcmds);
3104 }
3105}
3106
3107/*
3108 * Prepare the SQL command from st->use_file at command_num.
3109 */
3110static void
3111prepareCommand(CState *st, int command_num)
3112{
3113 Command *command = sql_script[st->use_file].commands[command_num];
3114
3115 /* No prepare for non-SQL commands */
3116 if (command->type != SQL_COMMAND)
3117 return;
3118
3119 if (!st->prepared)
3121
3122 if (!st->prepared[st->use_file][command_num])
3123 {
3124 PGresult *res;
3125
3126 pg_log_debug("client %d preparing %s", st->id, command->prepname);
3127 res = PQprepare(st->con, command->prepname,
3128 command->argv[0], command->argc - 1, NULL);
3129 if (PQresultStatus(res) != PGRES_COMMAND_OK)
3130 pg_log_error("%s", PQerrorMessage(st->con));
3131 PQclear(res);
3132 st->prepared[st->use_file][command_num] = true;
3133 }
3134}
3135
3136/*
3137 * Prepare all the commands in the script that come after the \startpipeline
3138 * that's at position st->command, and the first \endpipeline we find.
3139 *
3140 * This sets the ->prepared flag for each relevant command as well as the
3141 * \startpipeline itself, but doesn't move the st->command counter.
3142 */
3143static void
3145{
3146 int j;
3147 Command **commands = sql_script[st->use_file].commands;
3148
3149 Assert(commands[st->command]->type == META_COMMAND &&
3150 commands[st->command]->meta == META_STARTPIPELINE);
3151
3152 if (!st->prepared)
3154
3155 /*
3156 * We set the 'prepared' flag on the \startpipeline itself to flag that we
3157 * don't need to do this next time without calling prepareCommand(), even
3158 * though we don't actually prepare this command.
3159 */
3160 if (st->prepared[st->use_file][st->command])
3161 return;
3162
3163 for (j = st->command + 1; commands[j] != NULL; j++)
3164 {
3165 if (commands[j]->type == META_COMMAND &&
3166 commands[j]->meta == META_ENDPIPELINE)
3167 break;
3168
3169 prepareCommand(st, j);
3170 }
3171
3172 st->prepared[st->use_file][st->command] = true;
3173}
3174
3175/* Send a SQL command, using the chosen querymode */
3176static bool
3177sendCommand(CState *st, Command *command)
3178{
3179 int r;
3180
3181 if (querymode == QUERY_SIMPLE)
3182 {
3183 char *sql;
3184
3185 sql = pg_strdup(command->argv[0]);
3186 sql = assignVariables(&st->variables, sql);
3187
3188 pg_log_debug("client %d sending %s", st->id, sql);
3189 r = PQsendQuery(st->con, sql);
3190 free(sql);
3191 }
3192 else if (querymode == QUERY_EXTENDED)
3193 {
3194 const char *sql = command->argv[0];
3195 const char *params[MAX_ARGS];
3196
3197 getQueryParams(&st->variables, command, params);
3198
3199 pg_log_debug("client %d sending %s", st->id, sql);
3200 r = PQsendQueryParams(st->con, sql, command->argc - 1,
3201 NULL, params, NULL, NULL, 0);
3202 }
3203 else if (querymode == QUERY_PREPARED)
3204 {
3205 const char *params[MAX_ARGS];
3206
3207 prepareCommand(st, st->command);
3208 getQueryParams(&st->variables, command, params);
3209
3210 pg_log_debug("client %d sending %s", st->id, command->prepname);
3211 r = PQsendQueryPrepared(st->con, command->prepname, command->argc - 1,
3212 params, NULL, NULL, 0);
3213 }
3214 else /* unknown sql mode */
3215 r = 0;
3216
3217 if (r == 0)
3218 {
3219 pg_log_debug("client %d could not send %s", st->id, command->argv[0]);
3220 return false;
3221 }
3222 else
3223 return true;
3224}
3225
3226/*
3227 * Get the error status from the error code.
3228 */
3230getSQLErrorStatus(const char *sqlState)
3231{
3232 if (sqlState != NULL)
3233 {
3234 if (strcmp(sqlState, ERRCODE_T_R_SERIALIZATION_FAILURE) == 0)
3236 else if (strcmp(sqlState, ERRCODE_T_R_DEADLOCK_DETECTED) == 0)
3238 }
3239
3241}
3242
3243/*
3244 * Returns true if this type of error can be retried.
3245 */
3246static bool
3247canRetryError(EStatus estatus)
3248{
3249 return (estatus == ESTATUS_SERIALIZATION_ERROR ||
3250 estatus == ESTATUS_DEADLOCK_ERROR);
3251}
3252
3253/*
3254 * Process query response from the backend.
3255 *
3256 * If varprefix is not NULL, it's the variable name prefix where to store
3257 * the results of the *last* command (META_GSET) or *all* commands
3258 * (META_ASET).
3259 *
3260 * Returns true if everything is A-OK, false if any error occurs.
3261 */
3262static bool
3263readCommandResponse(CState *st, MetaCommand meta, char *varprefix)
3264{
3265 PGresult *res;
3266 PGresult *next_res;
3267 int qrynum = 0;
3268
3269 /*
3270 * varprefix should be set only with \gset or \aset, and \endpipeline and
3271 * SQL commands do not need it.
3272 */
3273 Assert((meta == META_NONE && varprefix == NULL) ||
3274 ((meta == META_ENDPIPELINE) && varprefix == NULL) ||
3275 ((meta == META_GSET || meta == META_ASET) && varprefix != NULL));
3276
3277 res = PQgetResult(st->con);
3278
3279 while (res != NULL)
3280 {
3281 bool is_last;
3282
3283 /* peek at the next result to know whether the current is last */
3284 next_res = PQgetResult(st->con);
3285 is_last = (next_res == NULL);
3286
3287 switch (PQresultStatus(res))
3288 {
3289 case PGRES_COMMAND_OK: /* non-SELECT commands */
3290 case PGRES_EMPTY_QUERY: /* may be used for testing no-op overhead */
3291 if (is_last && meta == META_GSET)
3292 {
3293 pg_log_error("client %d script %d command %d query %d: expected one row, got %d",
3294 st->id, st->use_file, st->command, qrynum, 0);
3296 goto error;
3297 }
3298 break;
3299
3300 case PGRES_TUPLES_OK:
3301 if ((is_last && meta == META_GSET) || meta == META_ASET)
3302 {
3303 int ntuples = PQntuples(res);
3304
3305 if (meta == META_GSET && ntuples != 1)
3306 {
3307 /* under \gset, report the error */
3308 pg_log_error("client %d script %d command %d query %d: expected one row, got %d",
3309 st->id, st->use_file, st->command, qrynum, PQntuples(res));
3311 goto error;
3312 }
3313 else if (meta == META_ASET && ntuples <= 0)
3314 {
3315 /* coldly skip empty result under \aset */
3316 break;
3317 }
3318
3319 /* store results into variables */
3320 for (int fld = 0; fld < PQnfields(res); fld++)
3321 {
3322 char *varname = PQfname(res, fld);
3323
3324 /* allocate varname only if necessary, freed below */
3325 if (*varprefix != '\0')
3326 varname = psprintf("%s%s", varprefix, varname);
3327
3328 /* store last row result as a string */
3329 if (!putVariable(&st->variables, meta == META_ASET ? "aset" : "gset", varname,
3330 PQgetvalue(res, ntuples - 1, fld)))
3331 {
3332 /* internal error */
3333 pg_log_error("client %d script %d command %d query %d: error storing into variable %s",
3334 st->id, st->use_file, st->command, qrynum, varname);
3336 goto error;
3337 }
3338
3339 if (*varprefix != '\0')
3340 pg_free(varname);
3341 }
3342 }
3343 /* otherwise the result is simply thrown away by PQclear below */
3344 break;
3345
3347 pg_log_debug("client %d pipeline ending, ongoing syncs: %d",
3348 st->id, st->num_syncs);
3349 st->num_syncs--;
3350 if (st->num_syncs == 0 && PQexitPipelineMode(st->con) != 1)
3351 pg_log_error("client %d failed to exit pipeline mode: %s", st->id,
3352 PQerrorMessage(st->con));
3353 break;
3354
3356 case PGRES_FATAL_ERROR:
3359 if (canRetryError(st->estatus))
3360 {
3361 if (verbose_errors)
3363 goto error;
3364 }
3365 /* fall through */
3366
3367 default:
3368 /* anything else is unexpected */
3369 pg_log_error("client %d script %d aborted in command %d query %d: %s",
3370 st->id, st->use_file, st->command, qrynum,
3371 PQerrorMessage(st->con));
3372 goto error;
3373 }
3374
3375 PQclear(res);
3376 qrynum++;
3377 res = next_res;
3378 }
3379
3380 if (qrynum == 0)
3381 {
3382 pg_log_error("client %d command %d: no results", st->id, st->command);
3383 return false;
3384 }
3385
3386 return true;
3387
3388error:
3389 PQclear(res);
3390 PQclear(next_res);
3391 do
3392 {
3393 res = PQgetResult(st->con);
3394 PQclear(res);
3395 } while (res);
3396
3397 return false;
3398}
3399
3400/*
3401 * Parse the argument to a \sleep command, and return the requested amount
3402 * of delay, in microseconds. Returns true on success, false on error.
3403 */
3404static bool
3405evaluateSleep(Variables *variables, int argc, char **argv, int *usecs)
3406{
3407 char *var;
3408 int usec;
3409
3410 if (*argv[1] == ':')
3411 {
3412 if ((var = getVariable(variables, argv[1] + 1)) == NULL)
3413 {
3414 pg_log_error("%s: undefined variable \"%s\"", argv[0], argv[1] + 1);
3415 return false;
3416 }
3417
3418 usec = atoi(var);
3419
3420 /* Raise an error if the value of a variable is not a number */
3421 if (usec == 0 && !isdigit((unsigned char) *var))
3422 {
3423 pg_log_error("%s: invalid sleep time \"%s\" for variable \"%s\"",
3424 argv[0], var, argv[1] + 1);
3425 return false;
3426 }
3427 }
3428 else
3429 usec = atoi(argv[1]);
3430
3431 if (argc > 2)
3432 {
3433 if (pg_strcasecmp(argv[2], "ms") == 0)
3434 usec *= 1000;
3435 else if (pg_strcasecmp(argv[2], "s") == 0)
3436 usec *= 1000000;
3437 }
3438 else
3439 usec *= 1000000;
3440
3441 *usecs = usec;
3442 return true;
3443}
3444
3445
3446/*
3447 * Returns true if the error can be retried.
3448 */
3449static bool
3451{
3453
3454 /* We can only retry serialization or deadlock errors. */
3455 if (!canRetryError(st->estatus))
3456 return false;
3457
3458 /*
3459 * We must have at least one option to limit the retrying of transactions
3460 * that got an error.
3461 */
3463
3464 /*
3465 * We cannot retry the error if we have reached the maximum number of
3466 * tries.
3467 */
3468 if (max_tries && st->tries >= max_tries)
3469 return false;
3470
3471 /*
3472 * We cannot retry the error if we spent too much time on this
3473 * transaction.
3474 */
3475 if (latency_limit)
3476 {
3478 if (*now - st->txn_scheduled > latency_limit)
3479 return false;
3480 }
3481
3482 /*
3483 * We cannot retry the error if the benchmark duration is over.
3484 */
3485 if (timer_exceeded)
3486 return false;
3487
3488 /* OK */
3489 return true;
3490}
3491
3492/*
3493 * Read results and discard it until a sync point.
3494 */
3495static int
3497{
3498 /* send a sync */
3499 if (!PQpipelineSync(st->con))
3500 {
3501 pg_log_error("client %d aborted: failed to send a pipeline sync",
3502 st->id);
3503 return 0;
3504 }
3505
3506 /* receive PGRES_PIPELINE_SYNC and null following it */
3507 for (;;)
3508 {
3509 PGresult *res = PQgetResult(st->con);
3510
3512 {
3513 PQclear(res);
3514 res = PQgetResult(st->con);
3515 Assert(res == NULL);
3516 break;
3517 }
3518 PQclear(res);
3519 }
3520
3521 /* exit pipeline */
3522 if (PQexitPipelineMode(st->con) != 1)
3523 {
3524 pg_log_error("client %d aborted: failed to exit pipeline mode for rolling back the failed transaction",
3525 st->id);
3526 return 0;
3527 }
3528 return 1;
3529}
3530
3531/*
3532 * Get the transaction status at the end of a command especially for
3533 * checking if we are in a (failed) transaction block.
3534 */
3537{
3538 PGTransactionStatusType tx_status;
3539
3540 tx_status = PQtransactionStatus(con);
3541 switch (tx_status)
3542 {
3543 case PQTRANS_IDLE:
3544 return TSTATUS_IDLE;
3545 case PQTRANS_INTRANS:
3546 case PQTRANS_INERROR:
3547 return TSTATUS_IN_BLOCK;
3548 case PQTRANS_UNKNOWN:
3549 /* PQTRANS_UNKNOWN is expected given a broken connection */
3550 if (PQstatus(con) == CONNECTION_BAD)
3551 return TSTATUS_CONN_ERROR;
3552 /* fall through */
3553 case PQTRANS_ACTIVE:
3554 default:
3555
3556 /*
3557 * We cannot find out whether we are in a transaction block or
3558 * not. Internal error which should never occur.
3559 */
3560 pg_log_error("unexpected transaction status %d", tx_status);
3561 return TSTATUS_OTHER_ERROR;
3562 }
3563
3564 /* not reached */
3565 Assert(false);
3566 return TSTATUS_OTHER_ERROR;
3567}
3568
3569/*
3570 * Print verbose messages of an error
3571 */
3572static void
3574{
3575 static PQExpBuffer buf = NULL;
3576
3577 if (buf == NULL)
3579 else
3581
3582 printfPQExpBuffer(buf, "client %d ", st->id);
3583 appendPQExpBufferStr(buf, (is_retry ?
3584 "repeats the transaction after the error" :
3585 "ends the failed transaction"));
3586 appendPQExpBuffer(buf, " (try %u", st->tries);
3587
3588 /* Print max_tries if it is not unlimited. */
3589 if (max_tries)
3591
3592 /*
3593 * If the latency limit is used, print a percentage of the current
3594 * transaction latency from the latency limit.
3595 */
3596 if (latency_limit)
3597 {
3599 appendPQExpBuffer(buf, ", %.3f%% of the maximum time of tries was used",
3600 (100.0 * (*now - st->txn_scheduled) / latency_limit));
3601 }
3602 appendPQExpBufferStr(buf, ")\n");
3603
3604 pg_log_info("%s", buf->data);
3605}
3606
3607/*
3608 * Advance the state machine of a connection.
3609 */
3610static void
3612{
3613
3614 /*
3615 * gettimeofday() isn't free, so we get the current timestamp lazily the
3616 * first time it's needed, and reuse the same value throughout this
3617 * function after that. This also ensures that e.g. the calculated
3618 * latency reported in the log file and in the totals are the same. Zero
3619 * means "not set yet". Reset "now" when we execute shell commands or
3620 * expressions, which might take a non-negligible amount of time, though.
3621 */
3622 pg_time_usec_t now = 0;
3623
3624 /*
3625 * Loop in the state machine, until we have to wait for a result from the
3626 * server or have to sleep for throttling or \sleep.
3627 *
3628 * Note: In the switch-statement below, 'break' will loop back here,
3629 * meaning "continue in the state machine". Return is used to return to
3630 * the caller, giving the thread the opportunity to advance another
3631 * client.
3632 */
3633 for (;;)
3634 {
3635 Command *command;
3636
3637 switch (st->state)
3638 {
3639 /* Select transaction (script) to run. */
3641 st->use_file = chooseScript(thread);
3643
3644 /* reset transaction variables to default values */
3646 st->tries = 1;
3647
3648 pg_log_debug("client %d executing script \"%s\"",
3649 st->id, sql_script[st->use_file].desc);
3650
3651 /*
3652 * If time is over, we're done; otherwise, get ready to start
3653 * a new transaction, or to get throttled if that's requested.
3654 */
3657 break;
3658
3659 /* Start new transaction (script) */
3660 case CSTATE_START_TX:
3662
3663 /* establish connection if needed, i.e. under --connect */
3664 if (st->con == NULL)
3665 {
3667
3668 if ((st->con = doConnect()) == NULL)
3669 {
3670 /*
3671 * as the bench is already running, we do not abort
3672 * the process
3673 */
3674 pg_log_error("client %d aborted while establishing connection", st->id);
3675 st->state = CSTATE_ABORTED;
3676 break;
3677 }
3678
3679 /* reset now after connection */
3680 now = pg_time_now();
3681
3682 thread->conn_duration += now - start;
3683
3684 /* Reset session-local state */
3685 pg_free(st->prepared);
3686 st->prepared = NULL;
3687 }
3688
3689 /*
3690 * It is the first try to run this transaction. Remember the
3691 * random state: maybe it will get an error and we will need
3692 * to run it again.
3693 */
3694 st->random_state = st->cs_func_rs;
3695
3696 /* record transaction start time */
3697 st->txn_begin = now;
3698
3699 /*
3700 * When not throttling, this is also the transaction's
3701 * scheduled start time.
3702 */
3703 if (!throttle_delay)
3704 st->txn_scheduled = now;
3705
3706 /* Begin with the first command */
3708 st->command = 0;
3709 break;
3710
3711 /*
3712 * Handle throttling once per transaction by sleeping.
3713 */
3715
3716 /*
3717 * Generate a delay such that the series of delays will
3718 * approximate a Poisson distribution centered on the
3719 * throttle_delay time.
3720 *
3721 * If transactions are too slow or a given wait is shorter
3722 * than a transaction, the next transaction will start right
3723 * away.
3724 */
3726
3727 thread->throttle_trigger +=
3729 st->txn_scheduled = thread->throttle_trigger;
3730
3731 /*
3732 * If --latency-limit is used, and this slot is already late
3733 * so that the transaction will miss the latency limit even if
3734 * it completed immediately, skip this time slot and loop to
3735 * reschedule.
3736 */
3737 if (latency_limit)
3738 {
3740
3741 if (thread->throttle_trigger < now - latency_limit)
3742 {
3743 processXactStats(thread, st, &now, true, agg);
3744
3745 /*
3746 * Finish client if -T or -t was exceeded.
3747 *
3748 * Stop counting skipped transactions under -T as soon
3749 * as the timer is exceeded. Because otherwise it can
3750 * take a very long time to count all of them
3751 * especially when quite a lot of them happen with
3752 * unrealistically high rate setting in -R, which
3753 * would prevent pgbench from ending immediately.
3754 * Because of this behavior, note that there is no
3755 * guarantee that all skipped transactions are counted
3756 * under -T though there is under -t. This is OK in
3757 * practice because it's very unlikely to happen with
3758 * realistic setting.
3759 */
3760 if (timer_exceeded || (nxacts > 0 && st->cnt >= nxacts))
3761 st->state = CSTATE_FINISHED;
3762
3763 /* Go back to top of loop with CSTATE_PREPARE_THROTTLE */
3764 break;
3765 }
3766 }
3767
3768 /*
3769 * stop client if next transaction is beyond pgbench end of
3770 * execution; otherwise, throttle it.
3771 */
3772 st->state = end_time > 0 && st->txn_scheduled > end_time ?
3774 break;
3775
3776 /*
3777 * Wait until it's time to start next transaction.
3778 */
3779 case CSTATE_THROTTLE:
3781
3782 if (now < st->txn_scheduled)
3783 return; /* still sleeping, nothing to do here */
3784
3785 /* done sleeping, but don't start transaction if we're done */
3787 break;
3788
3789 /*
3790 * Send a command to server (or execute a meta-command)
3791 */
3793 command = sql_script[st->use_file].commands[st->command];
3794
3795 /*
3796 * Transition to script end processing if done, but close up
3797 * shop if a pipeline is open at this point.
3798 */
3799 if (command == NULL)
3800 {
3802 st->state = CSTATE_END_TX;
3803 else
3804 {
3805 pg_log_error("client %d aborted: end of script reached with pipeline open",
3806 st->id);
3807 st->state = CSTATE_ABORTED;
3808 }
3809
3810 break;
3811 }
3812
3813 /* record begin time of next command, and initiate it */
3815 {
3817 st->stmt_begin = now;
3818 }
3819
3820 /* Execute the command */
3821 if (command->type == SQL_COMMAND)
3822 {
3823 /* disallow \aset and \gset in pipeline mode */
3825 {
3826 if (command->meta == META_GSET)
3827 {
3828 commandFailed(st, "gset", "\\gset is not allowed in pipeline mode");
3829 st->state = CSTATE_ABORTED;
3830 break;
3831 }
3832 else if (command->meta == META_ASET)
3833 {
3834 commandFailed(st, "aset", "\\aset is not allowed in pipeline mode");
3835 st->state = CSTATE_ABORTED;
3836 break;
3837 }
3838 }
3839
3840 if (!sendCommand(st, command))
3841 {
3842 commandFailed(st, "SQL", "SQL command send failed");
3843 st->state = CSTATE_ABORTED;
3844 }
3845 else
3846 {
3847 /* Wait for results, unless in pipeline mode */
3850 else
3852 }
3853 }
3854 else if (command->type == META_COMMAND)
3855 {
3856 /*-----
3857 * Possible state changes when executing meta commands:
3858 * - on errors CSTATE_ABORTED
3859 * - on sleep CSTATE_SLEEP
3860 * - else CSTATE_END_COMMAND
3861 */
3862 st->state = executeMetaCommand(st, &now);
3863 if (st->state == CSTATE_ABORTED)
3865 }
3866
3867 /*
3868 * We're now waiting for an SQL command to complete, or
3869 * finished processing a metacommand, or need to sleep, or
3870 * something bad happened.
3871 */
3873 st->state == CSTATE_END_COMMAND ||
3874 st->state == CSTATE_SLEEP ||
3875 st->state == CSTATE_ABORTED);
3876 break;
3877
3878 /*
3879 * non executed conditional branch
3880 */
3883 /* quickly skip commands until something to do... */
3884 while (true)
3885 {
3886 command = sql_script[st->use_file].commands[st->command];
3887
3888 /* cannot reach end of script in that state */
3889 Assert(command != NULL);
3890
3891 /*
3892 * if this is conditional related, update conditional
3893 * state
3894 */
3895 if (command->type == META_COMMAND &&
3896 (command->meta == META_IF ||
3897 command->meta == META_ELIF ||
3898 command->meta == META_ELSE ||
3899 command->meta == META_ENDIF))
3900 {
3901 switch (conditional_stack_peek(st->cstack))
3902 {
3903 case IFSTATE_FALSE:
3904 if (command->meta == META_IF)
3905 {
3906 /* nested if in skipped branch - ignore */
3909 st->command++;
3910 }
3911 else if (command->meta == META_ELIF)
3912 {
3913 /* we must evaluate the condition */
3915 }
3916 else if (command->meta == META_ELSE)
3917 {
3918 /* we must execute next command */
3922 st->command++;
3923 }
3924 else if (command->meta == META_ENDIF)
3925 {
3928 if (conditional_active(st->cstack))
3930 /* else state remains CSTATE_SKIP_COMMAND */
3931 st->command++;
3932 }
3933 break;
3934
3935 case IFSTATE_IGNORED:
3936 case IFSTATE_ELSE_FALSE:
3937 if (command->meta == META_IF)
3940 else if (command->meta == META_ENDIF)
3941 {
3944 if (conditional_active(st->cstack))
3946 }
3947 /* could detect "else" & "elif" after "else" */
3948 st->command++;
3949 break;
3950
3951 case IFSTATE_NONE:
3952 case IFSTATE_TRUE:
3953 case IFSTATE_ELSE_TRUE:
3954 default:
3955
3956 /*
3957 * inconsistent if inactive, unreachable dead
3958 * code
3959 */
3960 Assert(false);
3961 }
3962 }
3963 else
3964 {
3965 /* skip and consider next */
3966 st->command++;
3967 }
3968
3969 if (st->state != CSTATE_SKIP_COMMAND)
3970 /* out of quick skip command loop */
3971 break;
3972 }
3973 break;
3974
3975 /*
3976 * Wait for the current SQL command to complete
3977 */
3978 case CSTATE_WAIT_RESULT:
3979 pg_log_debug("client %d receiving", st->id);
3980
3981 /*
3982 * Only check for new network data if we processed all data
3983 * fetched prior. Otherwise we end up doing a syscall for each
3984 * individual pipelined query, which has a measurable
3985 * performance impact.
3986 */
3987 if (PQisBusy(st->con) && !PQconsumeInput(st->con))
3988 {
3989 /* there's something wrong */
3990 commandFailed(st, "SQL", "perhaps the backend died while processing");
3991 st->state = CSTATE_ABORTED;
3992 break;
3993 }
3994 if (PQisBusy(st->con))
3995 return; /* don't have the whole result yet */
3996
3997 /* store or discard the query results */
3998 if (readCommandResponse(st,
4001 {
4002 /*
4003 * outside of pipeline mode: stop reading results.
4004 * pipeline mode: continue reading results until an
4005 * end-of-pipeline response.
4006 */
4009 }
4010 else if (canRetryError(st->estatus))
4011 st->state = CSTATE_ERROR;
4012 else
4013 st->state = CSTATE_ABORTED;
4014 break;
4015
4016 /*
4017 * Wait until sleep is done. This state is entered after a
4018 * \sleep metacommand. The behavior is similar to
4019 * CSTATE_THROTTLE, but proceeds to CSTATE_START_COMMAND
4020 * instead of CSTATE_START_TX.
4021 */
4022 case CSTATE_SLEEP:
4024 if (now < st->sleep_until)
4025 return; /* still sleeping, nothing to do here */
4026 /* Else done sleeping. */
4028 break;
4029
4030 /*
4031 * End of command: record stats and proceed to next command.
4032 */
4033 case CSTATE_END_COMMAND:
4034
4035 /*
4036 * command completed: accumulate per-command execution times
4037 * in thread-local data structure, if per-command latencies
4038 * are requested.
4039 */
4041 {
4043
4044 command = sql_script[st->use_file].commands[st->command];
4045 /* XXX could use a mutex here, but we choose not to */
4046 addToSimpleStats(&command->stats,
4048 }
4049
4050 /* Go ahead with next command, to be executed or skipped */
4051 st->command++;
4052 st->state = conditional_active(st->cstack) ?
4054 break;
4055
4056 /*
4057 * Clean up after an error.
4058 */
4059 case CSTATE_ERROR:
4060 {
4061 TStatus tstatus;
4062
4064
4065 /* Clear the conditional stack */
4067
4068 /* Read and discard until a sync point in pipeline mode */
4070 {
4071 if (!discardUntilSync(st))
4072 {
4073 st->state = CSTATE_ABORTED;
4074 break;
4075 }
4076 }
4077
4078 /*
4079 * Check if we have a (failed) transaction block or not,
4080 * and roll it back if any.
4081 */
4082 tstatus = getTransactionStatus(st->con);
4083 if (tstatus == TSTATUS_IN_BLOCK)
4084 {
4085 /* Try to rollback a (failed) transaction block. */
4086 if (!PQsendQuery(st->con, "ROLLBACK"))
4087 {
4088 pg_log_error("client %d aborted: failed to send sql command for rolling back the failed transaction",
4089 st->id);
4090 st->state = CSTATE_ABORTED;
4091 }
4092 else
4094 }
4095 else if (tstatus == TSTATUS_IDLE)
4096 {
4097 /*
4098 * If time is over, we're done; otherwise, check if we
4099 * can retry the error.
4100 */
4103 }
4104 else
4105 {
4106 if (tstatus == TSTATUS_CONN_ERROR)
4107 pg_log_error("perhaps the backend died while processing");
4108
4109 pg_log_error("client %d aborted while receiving the transaction status", st->id);
4110 st->state = CSTATE_ABORTED;
4111 }
4112 break;
4113 }
4114
4115 /*
4116 * Wait for the rollback command to complete
4117 */
4119 {
4120 PGresult *res;
4121
4122 pg_log_debug("client %d receiving", st->id);
4123 if (!PQconsumeInput(st->con))
4124 {
4125 pg_log_error("client %d aborted while rolling back the transaction after an error; perhaps the backend died while processing",
4126 st->id);
4127 st->state = CSTATE_ABORTED;
4128 break;
4129 }
4130 if (PQisBusy(st->con))
4131 return; /* don't have the whole result yet */
4132
4133 /*
4134 * Read and discard the query result;
4135 */
4136 res = PQgetResult(st->con);
4137 switch (PQresultStatus(res))
4138 {
4139 case PGRES_COMMAND_OK:
4140 /* OK */
4141 PQclear(res);
4142 /* null must be returned */
4143 res = PQgetResult(st->con);
4144 Assert(res == NULL);
4145
4146 /*
4147 * If time is over, we're done; otherwise, check
4148 * if we can retry the error.
4149 */
4152 break;
4153 default:
4154 pg_log_error("client %d aborted while rolling back the transaction after an error; %s",
4155 st->id, PQerrorMessage(st->con));
4156 PQclear(res);
4157 st->state = CSTATE_ABORTED;
4158 break;
4159 }
4160 break;
4161 }
4162
4163 /*
4164 * Retry the transaction after an error.
4165 */
4166 case CSTATE_RETRY:
4167 command = sql_script[st->use_file].commands[st->command];
4168
4169 /*
4170 * Inform that the transaction will be retried after the
4171 * error.
4172 */
4173 if (verbose_errors)
4174 printVerboseErrorMessages(st, &now, true);
4175
4176 /* Count tries and retries */
4177 st->tries++;
4178 command->retries++;
4179
4180 /*
4181 * Reset the random state as they were at the beginning of the
4182 * transaction.
4183 */
4184 st->cs_func_rs = st->random_state;
4185
4186 /* Process the first transaction command. */
4187 st->command = 0;
4190 break;
4191
4192 /*
4193 * Record a failed transaction.
4194 */
4195 case CSTATE_FAILURE:
4196 command = sql_script[st->use_file].commands[st->command];
4197
4198 /* Accumulate the failure. */
4199 command->failures++;
4200
4201 /*
4202 * Inform that the failed transaction will not be retried.
4203 */
4204 if (verbose_errors)
4205 printVerboseErrorMessages(st, &now, false);
4206
4207 /* End the failed transaction. */
4208 st->state = CSTATE_END_TX;
4209 break;
4210
4211 /*
4212 * End of transaction (end of script, really).
4213 */
4214 case CSTATE_END_TX:
4215 {
4216 TStatus tstatus;
4217
4218 /* transaction finished: calculate latency and do log */
4219 processXactStats(thread, st, &now, false, agg);
4220
4221 /*
4222 * missing \endif... cannot happen if CheckConditional was
4223 * okay
4224 */
4226
4227 /*
4228 * We must complete all the transaction blocks that were
4229 * started in this script.
4230 */
4231 tstatus = getTransactionStatus(st->con);
4232 if (tstatus == TSTATUS_IN_BLOCK)
4233 {
4234 pg_log_error("client %d aborted: end of script reached without completing the last transaction",
4235 st->id);
4236 st->state = CSTATE_ABORTED;
4237 break;
4238 }
4239 else if (tstatus != TSTATUS_IDLE)
4240 {
4241 if (tstatus == TSTATUS_CONN_ERROR)
4242 pg_log_error("perhaps the backend died while processing");
4243
4244 pg_log_error("client %d aborted while receiving the transaction status", st->id);
4245 st->state = CSTATE_ABORTED;
4246 break;
4247 }
4248
4249 if (is_connect)
4250 {
4252
4254 finishCon(st);
4255 now = pg_time_now();
4256 thread->conn_duration += now - start;
4257 }
4258
4259 if ((st->cnt >= nxacts && duration <= 0) || timer_exceeded)
4260 {
4261 /* script completed */
4262 st->state = CSTATE_FINISHED;
4263 break;
4264 }
4265
4266 /* next transaction (script) */
4268
4269 /*
4270 * Ensure that we always return on this point, so as to
4271 * avoid an infinite loop if the script only contains meta
4272 * commands.
4273 */
4274 return;
4275 }
4276
4277 /*
4278 * Final states. Close the connection if it's still open.
4279 */
4280 case CSTATE_ABORTED:
4281 case CSTATE_FINISHED:
4282
4283 /*
4284 * Don't measure the disconnection delays here even if in
4285 * CSTATE_FINISHED and -C/--connect option is specified.
4286 * Because in this case all the connections that this thread
4287 * established are closed at the end of transactions and the
4288 * disconnection delays should have already been measured at
4289 * that moment.
4290 *
4291 * In CSTATE_ABORTED state, the measurement is no longer
4292 * necessary because we cannot report complete results anyways
4293 * in this case.
4294 */
4295 finishCon(st);
4296 return;
4297 }
4298 }
4299}
4300
4301/*
4302 * Subroutine for advanceConnectionState -- initiate or execute the current
4303 * meta command, and return the next state to set.
4304 *
4305 * *now is updated to the current time, unless the command is expected to
4306 * take no time to execute.
4307 */
4310{
4311 Command *command = sql_script[st->use_file].commands[st->command];
4312 int argc;
4313 char **argv;
4314
4315 Assert(command != NULL && command->type == META_COMMAND);
4316
4317 argc = command->argc;
4318 argv = command->argv;
4319
4321 {
4323
4325
4326 printfPQExpBuffer(&buf, "client %d executing \\%s", st->id, argv[0]);
4327 for (int i = 1; i < argc; i++)
4328 appendPQExpBuffer(&buf, " %s", argv[i]);
4329
4330 pg_log_debug("%s", buf.data);
4331
4333 }
4334
4335 if (command->meta == META_SLEEP)
4336 {
4337 int usec;
4338
4339 /*
4340 * A \sleep doesn't execute anything, we just get the delay from the
4341 * argument, and enter the CSTATE_SLEEP state. (The per-command
4342 * latency will be recorded in CSTATE_SLEEP state, not here, after the
4343 * delay has elapsed.)
4344 */
4345 if (!evaluateSleep(&st->variables, argc, argv, &usec))
4346 {
4347 commandFailed(st, "sleep", "execution of meta-command failed");
4348 return CSTATE_ABORTED;
4349 }
4350
4352 st->sleep_until = (*now) + usec;
4353 return CSTATE_SLEEP;
4354 }
4355 else if (command->meta == META_SET)
4356 {
4357 PgBenchExpr *expr = command->expr;
4358 PgBenchValue result;
4359
4360 if (!evaluateExpr(st, expr, &result))
4361 {
4362 commandFailed(st, argv[0], "evaluation of meta-command failed");
4363 return CSTATE_ABORTED;
4364 }
4365
4366 if (!putVariableValue(&st->variables, argv[0], argv[1], &result))
4367 {
4368 commandFailed(st, "set", "assignment of meta-command failed");
4369 return CSTATE_ABORTED;
4370 }
4371 }
4372 else if (command->meta == META_IF)
4373 {
4374 /* backslash commands with an expression to evaluate */
4375 PgBenchExpr *expr = command->expr;
4376 PgBenchValue result;
4377 bool cond;
4378
4379 if (!evaluateExpr(st, expr, &result))
4380 {
4381 commandFailed(st, argv[0], "evaluation of meta-command failed");
4382 return CSTATE_ABORTED;
4383 }
4384
4385 cond = valueTruth(&result);
4387 }
4388 else if (command->meta == META_ELIF)
4389 {
4390 /* backslash commands with an expression to evaluate */
4391 PgBenchExpr *expr = command->expr;
4392 PgBenchValue result;
4393 bool cond;
4394
4396 {
4397 /* elif after executed block, skip eval and wait for endif. */
4399 return CSTATE_END_COMMAND;
4400 }
4401
4402 if (!evaluateExpr(st, expr, &result))
4403 {
4404 commandFailed(st, argv[0], "evaluation of meta-command failed");
4405 return CSTATE_ABORTED;
4406 }
4407
4408 cond = valueTruth(&result);
4411 }
4412 else if (command->meta == META_ELSE)
4413 {
4414 switch (conditional_stack_peek(st->cstack))
4415 {
4416 case IFSTATE_TRUE:
4418 break;
4419 case IFSTATE_FALSE: /* inconsistent if active */
4420 case IFSTATE_IGNORED: /* inconsistent if active */
4421 case IFSTATE_NONE: /* else without if */
4422 case IFSTATE_ELSE_TRUE: /* else after else */
4423 case IFSTATE_ELSE_FALSE: /* else after else */
4424 default:
4425 /* dead code if conditional check is ok */
4426 Assert(false);
4427 }
4428 }
4429 else if (command->meta == META_ENDIF)
4430 {
4433 }
4434 else if (command->meta == META_SETSHELL)
4435 {
4436 if (!runShellCommand(&st->variables, argv[1], argv + 2, argc - 2))
4437 {
4438 commandFailed(st, "setshell", "execution of meta-command failed");
4439 return CSTATE_ABORTED;
4440 }
4441 }
4442 else if (command->meta == META_SHELL)
4443 {
4444 if (!runShellCommand(&st->variables, NULL, argv + 1, argc - 1))
4445 {
4446 commandFailed(st, "shell", "execution of meta-command failed");
4447 return CSTATE_ABORTED;
4448 }
4449 }
4450 else if (command->meta == META_STARTPIPELINE)
4451 {
4452 /*
4453 * In pipeline mode, we use a workflow based on libpq pipeline
4454 * functions.
4455 */
4456 if (querymode == QUERY_SIMPLE)
4457 {
4458 commandFailed(st, "startpipeline", "cannot use pipeline mode with the simple query protocol");
4459 return CSTATE_ABORTED;
4460 }
4461
4462 /*
4463 * If we're in prepared-query mode, we need to prepare all the
4464 * commands that are inside the pipeline before we actually start the
4465 * pipeline itself. This solves the problem that running BEGIN
4466 * ISOLATION LEVEL SERIALIZABLE in a pipeline would fail due to a
4467 * snapshot having been acquired by the prepare within the pipeline.
4468 */
4471
4473 {
4474 commandFailed(st, "startpipeline", "already in pipeline mode");
4475 return CSTATE_ABORTED;
4476 }
4477 if (PQenterPipelineMode(st->con) == 0)
4478 {
4479 commandFailed(st, "startpipeline", "failed to enter pipeline mode");
4480 return CSTATE_ABORTED;
4481 }
4482 }
4483 else if (command->meta == META_SYNCPIPELINE)
4484 {
4486 {
4487 commandFailed(st, "syncpipeline", "not in pipeline mode");
4488 return CSTATE_ABORTED;
4489 }
4490 if (PQsendPipelineSync(st->con) == 0)
4491 {
4492 commandFailed(st, "syncpipeline", "failed to send a pipeline sync");
4493 return CSTATE_ABORTED;
4494 }
4495 st->num_syncs++;
4496 }
4497 else if (command->meta == META_ENDPIPELINE)
4498 {
4500 {
4501 commandFailed(st, "endpipeline", "not in pipeline mode");
4502 return CSTATE_ABORTED;
4503 }
4504 if (!PQpipelineSync(st->con))
4505 {
4506 commandFailed(st, "endpipeline", "failed to send a pipeline sync");
4507 return CSTATE_ABORTED;
4508 }
4509 st->num_syncs++;
4510 /* Now wait for the PGRES_PIPELINE_SYNC and exit pipeline mode there */
4511 /* collect pending results before getting out of pipeline mode */
4512 return CSTATE_WAIT_RESULT;
4513 }
4514
4515 /*
4516 * executing the expression or shell command might have taken a
4517 * non-negligible amount of time, so reset 'now'
4518 */
4519 *now = 0;
4520
4521 return CSTATE_END_COMMAND;
4522}
4523
4524/*
4525 * Return the number of failed transactions.
4526 */
4527static int64
4528getFailures(const StatsData *stats)
4529{
4530 return (stats->serialization_failures +
4531 stats->deadlock_failures);
4532}
4533
4534/*
4535 * Return a string constant representing the result of a transaction
4536 * that is not successfully processed.
4537 */
4538static const char *
4539getResultString(bool skipped, EStatus estatus)
4540{
4541 if (skipped)
4542 return "skipped";
4543 else if (failures_detailed)
4544 {
4545 switch (estatus)
4546 {
4548 return "serialization";
4550 return "deadlock";
4551 default:
4552 /* internal error which should never occur */
4553 pg_fatal("unexpected error status: %d", estatus);
4554 }
4555 }
4556 else
4557 return "failed";
4558}
4559
4560/*
4561 * Print log entry after completing one transaction.
4562 *
4563 * We print Unix-epoch timestamps in the log, so that entries can be
4564 * correlated against other logs.
4565 *
4566 * XXX We could obtain the time from the caller and just shift it here, to
4567 * avoid the cost of an extra call to pg_time_now().
4568 */
4569static void
4570doLog(TState *thread, CState *st,
4571 StatsData *agg, bool skipped, double latency, double lag)
4572{
4573 FILE *logfile = thread->logfile;
4575
4576 Assert(use_log);
4577
4578 /*
4579 * Skip the log entry if sampling is enabled and this row doesn't belong
4580 * to the random sample.
4581 */
4582 if (sample_rate != 0.0 &&
4584 return;
4585
4586 /* should we aggregate the results or not? */
4587 if (agg_interval > 0)
4588 {
4590
4591 /*
4592 * Loop until we reach the interval of the current moment, and print
4593 * any empty intervals in between (this may happen with very low tps,
4594 * e.g. --rate=0.1).
4595 */
4596
4597 while ((next = agg->start_time + agg_interval * INT64CONST(1000000)) <= now)
4598 {
4599 double lag_sum = 0.0;
4600 double lag_sum2 = 0.0;
4601 double lag_min = 0.0;
4602 double lag_max = 0.0;
4603 int64 skipped = 0;
4604 int64 serialization_failures = 0;
4605 int64 deadlock_failures = 0;
4606 int64 retried = 0;
4607 int64 retries = 0;
4608
4609 /* print aggregated report to logfile */
4610 fprintf(logfile, INT64_FORMAT " " INT64_FORMAT " %.0f %.0f %.0f %.0f",
4611 agg->start_time / 1000000, /* seconds since Unix epoch */
4612 agg->cnt,
4613 agg->latency.sum,
4614 agg->latency.sum2,
4615 agg->latency.min,
4616 agg->latency.max);
4617
4618 if (throttle_delay)
4619 {
4620 lag_sum = agg->lag.sum;
4621 lag_sum2 = agg->lag.sum2;
4622 lag_min = agg->lag.min;
4623 lag_max = agg->lag.max;
4624 }
4625 fprintf(logfile, " %.0f %.0f %.0f %.0f",
4626 lag_sum,
4627 lag_sum2,
4628 lag_min,
4629 lag_max);
4630
4631 if (latency_limit)
4632 skipped = agg->skipped;
4633 fprintf(logfile, " " INT64_FORMAT, skipped);
4634
4635 if (max_tries != 1)
4636 {
4637 retried = agg->retried;
4638 retries = agg->retries;
4639 }
4640 fprintf(logfile, " " INT64_FORMAT " " INT64_FORMAT, retried, retries);
4641
4643 {
4644 serialization_failures = agg->serialization_failures;
4645 deadlock_failures = agg->deadlock_failures;
4646 }
4648 serialization_failures,
4649 deadlock_failures);
4650
4651 fputc('\n', logfile);
4652
4653 /* reset data and move to next interval */
4654 initStats(agg, next);
4655 }
4656
4657 /* accumulate the current transaction */
4658 accumStats(agg, skipped, latency, lag, st->estatus, st->tries);
4659 }
4660 else
4661 {
4662 /* no, print raw transactions */
4663 if (!skipped && st->estatus == ESTATUS_NO_ERROR)
4664 fprintf(logfile, "%d " INT64_FORMAT " %.0f %d " INT64_FORMAT " "
4666 st->id, st->cnt, latency, st->use_file,
4667 now / 1000000, now % 1000000);
4668 else
4669 fprintf(logfile, "%d " INT64_FORMAT " %s %d " INT64_FORMAT " "
4671 st->id, st->cnt, getResultString(skipped, st->estatus),
4672 st->use_file, now / 1000000, now % 1000000);
4673
4674 if (throttle_delay)
4675 fprintf(logfile, " %.0f", lag);
4676 if (max_tries != 1)
4677 fprintf(logfile, " %u", st->tries - 1);
4678 fputc('\n', logfile);
4679 }
4680}
4681
4682/*
4683 * Accumulate and report statistics at end of a transaction.
4684 *
4685 * (This is also called when a transaction is late and thus skipped.
4686 * Note that even skipped and failed transactions are counted in the CState
4687 * "cnt" field.)
4688 */
4689static void
4691 bool skipped, StatsData *agg)
4692{
4693 double latency = 0.0,
4694 lag = 0.0;
4695 bool detailed = progress || throttle_delay || latency_limit ||
4697
4698 if (detailed && !skipped && st->estatus == ESTATUS_NO_ERROR)
4699 {
4701
4702 /* compute latency & lag */
4703 latency = (*now) - st->txn_scheduled;
4704 lag = st->txn_begin - st->txn_scheduled;
4705 }
4706
4707 /* keep detailed thread stats */
4708 accumStats(&thread->stats, skipped, latency, lag, st->estatus, st->tries);
4709
4710 /* count transactions over the latency limit, if needed */
4711 if (latency_limit && latency > latency_limit)
4712 thread->latency_late++;
4713
4714 /* client stat is just counting */
4715 st->cnt++;
4716
4717 if (use_log)
4718 doLog(thread, st, agg, skipped, latency, lag);
4719
4720 /* XXX could use a mutex here, but we choose not to */
4721 if (per_script_stats)
4722 accumStats(&sql_script[st->use_file].stats, skipped, latency, lag,
4723 st->estatus, st->tries);
4724}
4725
4726
4727/* discard connections */
4728static void
4729disconnect_all(CState *state, int length)
4730{
4731 int i;
4732
4733 for (i = 0; i < length; i++)
4734 finishCon(&state[i]);
4735}
4736
4737/*
4738 * Remove old pgbench tables, if any exist
4739 */
4740static void
4742{
4743 fprintf(stderr, "dropping old tables...\n");
4744
4745 /*
4746 * We drop all the tables in one command, so that whether there are
4747 * foreign key dependencies or not doesn't matter.
4748 */
4749 executeStatement(con, "drop table if exists "
4750 "pgbench_accounts, "
4751 "pgbench_branches, "
4752 "pgbench_history, "
4753 "pgbench_tellers");
4754}
4755
4756/*
4757 * Create "pgbench_accounts" partitions if needed.
4758 *
4759 * This is the larger table of pgbench default tpc-b like schema
4760 * with a known size, so we choose to partition it.
4761 */
4762static void
4764{
4765 PQExpBufferData query;
4766
4767 /* we must have to create some partitions */
4768 Assert(partitions > 0);
4769
4770 fprintf(stderr, "creating %d partitions...\n", partitions);
4771
4772 initPQExpBuffer(&query);
4773
4774 for (int p = 1; p <= partitions; p++)
4775 {
4777 {
4778 int64 part_size = (naccounts * (int64) scale + partitions - 1) / partitions;
4779
4780 printfPQExpBuffer(&query,
4781 "create%s table pgbench_accounts_%d\n"
4782 " partition of pgbench_accounts\n"
4783 " for values from (",
4784 unlogged_tables ? " unlogged" : "", p);
4785
4786 /*
4787 * For RANGE, we use open-ended partitions at the beginning and
4788 * end to allow any valid value for the primary key. Although the
4789 * actual minimum and maximum values can be derived from the
4790 * scale, it is more generic and the performance is better.
4791 */
4792 if (p == 1)
4793 appendPQExpBufferStr(&query, "minvalue");
4794 else
4795 appendPQExpBuffer(&query, INT64_FORMAT, (p - 1) * part_size + 1);
4796
4797 appendPQExpBufferStr(&query, ") to (");
4798
4799 if (p < partitions)
4800 appendPQExpBuffer(&query, INT64_FORMAT, p * part_size + 1);
4801 else
4802 appendPQExpBufferStr(&query, "maxvalue");
4803
4804 appendPQExpBufferChar(&query, ')');
4805 }
4806 else if (partition_method == PART_HASH)
4807 printfPQExpBuffer(&query,
4808 "create%s table pgbench_accounts_%d\n"
4809 " partition of pgbench_accounts\n"
4810 " for values with (modulus %d, remainder %d)",
4811 unlogged_tables ? " unlogged" : "", p,
4812 partitions, p - 1);
4813 else /* cannot get there */
4814 Assert(0);
4815
4816 /*
4817 * Per ddlinfo in initCreateTables, fillfactor is needed on table
4818 * pgbench_accounts.
4819 */
4820 appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
4821
4822 executeStatement(con, query.data);
4823 }
4824
4825 termPQExpBuffer(&query);
4826}
4827
4828/*
4829 * Create pgbench's standard tables
4830 */
4831static void
4833{
4834 /*
4835 * Note: TPC-B requires at least 100 bytes per row, and the "filler"
4836 * fields in these table declarations were intended to comply with that.
4837 * The pgbench_accounts table complies with that because the "filler"
4838 * column is set to blank-padded empty string. But for all other tables
4839 * the columns default to NULL and so don't actually take any space. We
4840 * could fix that by giving them non-null default values. However, that
4841 * would completely break comparability of pgbench results with prior
4842 * versions. Since pgbench has never pretended to be fully TPC-B compliant
4843 * anyway, we stick with the historical behavior.
4844 */
4845 struct ddlinfo
4846 {
4847 const char *table; /* table name */
4848 const char *smcols; /* column decls if accountIDs are 32 bits */
4849 const char *bigcols; /* column decls if accountIDs are 64 bits */
4850 int declare_fillfactor;
4851 };
4852 static const struct ddlinfo DDLs[] = {
4853 {
4854 "pgbench_history",
4855 "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
4856 "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)",
4857 0
4858 },
4859 {
4860 "pgbench_tellers",
4861 "tid int not null,bid int,tbalance int,filler char(84)",
4862 "tid int not null,bid int,tbalance int,filler char(84)",
4863 1
4864 },
4865 {
4866 "pgbench_accounts",
4867 "aid int not null,bid int,abalance int,filler char(84)",
4868 "aid bigint not null,bid int,abalance int,filler char(84)",
4869 1
4870 },
4871 {
4872 "pgbench_branches",
4873 "bid int not null,bbalance int,filler char(88)",
4874 "bid int not null,bbalance int,filler char(88)",
4875 1
4876 }
4877 };
4878 int i;
4879 PQExpBufferData query;
4880
4881 fprintf(stderr, "creating tables...\n");
4882
4883 initPQExpBuffer(&query);
4884
4885 for (i = 0; i < lengthof(DDLs); i++)
4886 {
4887 const struct ddlinfo *ddl = &DDLs[i];
4888
4889 /* Construct new create table statement. */
4890 printfPQExpBuffer(&query, "create%s table %s(%s)",
4891 (unlogged_tables && partition_method == PART_NONE) ? " unlogged" : "",
4892 ddl->table,
4893 (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols);
4894
4895 /* Partition pgbench_accounts table */
4896 if (partition_method != PART_NONE && strcmp(ddl->table, "pgbench_accounts") == 0)
4897 appendPQExpBuffer(&query,
4898 " partition by %s (aid)", PARTITION_METHOD[partition_method]);
4899 else if (ddl->declare_fillfactor)
4900 {
4901 /* fillfactor is only expected on actual tables */
4902 appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
4903 }
4904
4905 if (tablespace != NULL)
4906 {
4907 char *escape_tablespace;
4908
4909 escape_tablespace = PQescapeIdentifier(con, tablespace, strlen(tablespace));
4910 appendPQExpBuffer(&query, " tablespace %s", escape_tablespace);
4911 PQfreemem(escape_tablespace);
4912 }
4913
4914 executeStatement(con, query.data);
4915 }
4916
4917 termPQExpBuffer(&query);
4918
4920 createPartitions(con);
4921}
4922
4923/*
4924 * Truncate away any old data, in one command in case there are foreign keys
4925 */
4926static void
4928{
4929 executeStatement(con, "truncate table "
4930 "pgbench_accounts, "
4931 "pgbench_branches, "
4932 "pgbench_history, "
4933 "pgbench_tellers");
4934}
4935
4936static void
4938{
4939 /* "filler" column uses NULL */
4941 INT64_FORMAT "\t0\t\\N\n",
4942 curr + 1);
4943}
4944
4945static void
4947{
4948 /* "filler" column uses NULL */
4950 INT64_FORMAT "\t" INT64_FORMAT "\t0\t\\N\n",
4951 curr + 1, curr / ntellers + 1);
4952}
4953
4954static void
4956{
4957 /* "filler" column defaults to blank padded empty string */
4959 INT64_FORMAT "\t" INT64_FORMAT "\t0\t\n",
4960 curr + 1, curr / naccounts + 1);
4961}
4962
4963static void
4964initPopulateTable(PGconn *con, const char *table, int64 base,
4965 initRowMethod init_row)
4966{
4967 int n;
4968 int64 k;
4969 int chars = 0;
4970 int prev_chars = 0;
4971 PGresult *res;
4972 PQExpBufferData sql;
4973 char copy_statement[256];
4974 const char *copy_statement_fmt = "copy %s from stdin";
4975 int64 total = base * scale;
4976
4977 /* used to track elapsed time and estimate of the remaining time */
4979 int log_interval = 1;
4980
4981 /* Stay on the same line if reporting to a terminal */
4982 char eol = isatty(fileno(stderr)) ? '\r' : '\n';
4983
4984 initPQExpBuffer(&sql);
4985
4986 /* Use COPY with FREEZE on v14 and later for all ordinary tables */
4987 if ((PQserverVersion(con) >= 140000) &&
4988 get_table_relkind(con, table) == RELKIND_RELATION)
4989 copy_statement_fmt = "copy %s from stdin with (freeze on)";
4990
4991
4992 n = pg_snprintf(copy_statement, sizeof(copy_statement), copy_statement_fmt, table);
4993 if (n >= sizeof(copy_statement))
4994 pg_fatal("invalid buffer size: must be at least %d characters long", n);
4995 else if (n == -1)
4996 pg_fatal("invalid format string");
4997
4998 res = PQexec(con, copy_statement);
4999
5000 if (PQresultStatus(res) != PGRES_COPY_IN)
5001 pg_fatal("unexpected copy in result: %s", PQerrorMessage(con));
5002 PQclear(res);
5003
5004 start = pg_time_now();
5005
5006 for (k = 0; k < total; k++)
5007 {
5008 int64 j = k + 1;
5009
5010 init_row(&sql, k);
5011 if (PQputline(con, sql.data))
5012 pg_fatal("PQputline failed");
5013
5014 if (CancelRequested)
5015 break;
5016
5017 /*
5018 * If we want to stick with the original logging, print a message each
5019 * 100k inserted rows.
5020 */
5021 if ((!use_quiet) && (j % 100000 == 0))
5022 {
5023 double elapsed_sec = PG_TIME_GET_DOUBLE(pg_time_now() - start);
5024 double remaining_sec = ((double) total - j) * elapsed_sec / j;
5025
5026 chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)",
5027 j, total,
5028 (int) ((j * 100) / total),
5029 table, elapsed_sec, remaining_sec);
5030
5031 /*
5032 * If the previous progress message is longer than the current
5033 * one, add spaces to the current line to fully overwrite any
5034 * remaining characters from the previous message.
5035 */
5036 if (prev_chars > chars)
5037 fprintf(stderr, "%*c", prev_chars - chars, ' ');
5038 fputc(eol, stderr);
5039 prev_chars = chars;
5040 }
5041 /* let's not call the timing for each row, but only each 100 rows */
5042 else if (use_quiet && (j % 100 == 0))
5043 {
5044 double elapsed_sec = PG_TIME_GET_DOUBLE(pg_time_now() - start);
5045 double remaining_sec = ((double) total - j) * elapsed_sec / j;
5046
5047 /* have we reached the next interval (or end)? */
5048 if ((j == total) || (elapsed_sec >= log_interval * LOG_STEP_SECONDS))
5049 {
5050 chars = fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) of %s done (elapsed %.2f s, remaining %.2f s)",
5051 j, total,
5052 (int) ((j * 100) / total),
5053 table, elapsed_sec, remaining_sec);
5054
5055 /*
5056 * If the previous progress message is longer than the current
5057 * one, add spaces to the current line to fully overwrite any
5058 * remaining characters from the previous message.
5059 */
5060 if (prev_chars > chars)
5061 fprintf(stderr, "%*c", prev_chars - chars, ' ');
5062 fputc(eol, stderr);
5063 prev_chars = chars;
5064
5065 /* skip to the next interval */
5066 log_interval = (int) ceil(elapsed_sec / LOG_STEP_SECONDS);
5067 }
5068 }
5069 }
5070
5071 if (chars != 0 && eol != '\n')
5072 fprintf(stderr, "%*c\r", chars, ' '); /* Clear the current line */
5073
5074 if (PQputline(con, "\\.\n"))
5075 pg_fatal("very last PQputline failed");
5076 if (PQendcopy(con))
5077 pg_fatal("PQendcopy failed");
5078
5079 termPQExpBuffer(&sql);
5080}
5081
5082/*
5083 * Fill the standard tables with some data generated and sent from the client.
5084 *
5085 * The filler column is NULL in pgbench_branches and pgbench_tellers, and is
5086 * a blank-padded string in pgbench_accounts.
5087 */
5088static void
5090{
5091 fprintf(stderr, "generating data (client-side)...\n");
5092
5093 /*
5094 * we do all of this in one transaction to enable the backend's
5095 * data-loading optimizations
5096 */
5097 executeStatement(con, "begin");
5098
5099 /* truncate away any old data */
5100 initTruncateTables(con);
5101
5102 /*
5103 * fill branches, tellers, accounts in that order in case foreign keys
5104 * already exist
5105 */
5106 initPopulateTable(con, "pgbench_branches", nbranches, initBranch);
5107 initPopulateTable(con, "pgbench_tellers", ntellers, initTeller);
5108 initPopulateTable(con, "pgbench_accounts", naccounts, initAccount);
5109
5110 executeStatement(con, "commit");
5111}
5112
5113/*
5114 * Fill the standard tables with some data generated on the server
5115 *
5116 * As already the case with the client-side data generation, the filler
5117 * column defaults to NULL in pgbench_branches and pgbench_tellers,
5118 * and is a blank-padded string in pgbench_accounts.
5119 */
5120static void
5122{
5123 PQExpBufferData sql;
5124
5125 fprintf(stderr, "generating data (server-side)...\n");
5126
5127 /*
5128 * we do all of this in one transaction to enable the backend's
5129 * data-loading optimizations
5130 */
5131 executeStatement(con, "begin");
5132
5133 /* truncate away any old data */
5134 initTruncateTables(con);
5135
5136 initPQExpBuffer(&sql);
5137
5138 printfPQExpBuffer(&sql,
5139 "insert into pgbench_branches(bid,bbalance) "
5140 "select bid, 0 "
5141 "from generate_series(1, %d) as bid", nbranches * scale);
5142 executeStatement(con, sql.data);
5143
5144 printfPQExpBuffer(&sql,
5145 "insert into pgbench_tellers(tid,bid,tbalance) "
5146 "select tid, (tid - 1) / %d + 1, 0 "
5147 "from generate_series(1, %d) as tid", ntellers, ntellers * scale);
5148 executeStatement(con, sql.data);
5149
5150 printfPQExpBuffer(&sql,
5151 "insert into pgbench_accounts(aid,bid,abalance,filler) "
5152 "select aid, (aid - 1) / %d + 1, 0, '' "
5153 "from generate_series(1, " INT64_FORMAT ") as aid",
5155 executeStatement(con, sql.data);
5156
5157 termPQExpBuffer(&sql);
5158
5159 executeStatement(con, "commit");
5160}
5161
5162/*
5163 * Invoke vacuum on the standard tables
5164 */
5165static void
5166initVacuum(PGconn *con)
5167{
5168 fprintf(stderr, "vacuuming...\n");
5169 executeStatement(con, "vacuum analyze pgbench_branches");
5170 executeStatement(con, "vacuum analyze pgbench_tellers");
5171 executeStatement(con, "vacuum analyze pgbench_accounts");
5172 executeStatement(con, "vacuum analyze pgbench_history");
5173}
5174
5175/*
5176 * Create primary keys on the standard tables
5177 */
5178static void
5180{
5181 static const char *const DDLINDEXes[] = {
5182 "alter table pgbench_branches add primary key (bid)",
5183 "alter table pgbench_tellers add primary key (tid)",
5184 "alter table pgbench_accounts add primary key (aid)"
5185 };
5186 int i;
5187 PQExpBufferData query;
5188
5189 fprintf(stderr, "creating primary keys...\n");
5190 initPQExpBuffer(&query);
5191
5192 for (i = 0; i < lengthof(DDLINDEXes); i++)
5193 {
5194 resetPQExpBuffer(&query);
5195 appendPQExpBufferStr(&query, DDLINDEXes[i]);
5196
5197 if (index_tablespace != NULL)
5198 {
5199 char *escape_tablespace;
5200
5201 escape_tablespace = PQescapeIdentifier(con, index_tablespace,
5202 strlen(index_tablespace));
5203 appendPQExpBuffer(&query, " using index tablespace %s", escape_tablespace);
5204 PQfreemem(escape_tablespace);
5205 }
5206
5207 executeStatement(con, query.data);
5208 }
5209
5210 termPQExpBuffer(&query);
5211}
5212
5213/*
5214 * Create foreign key constraints between the standard tables
5215 */
5216static void
5218{
5219 static const char *const DDLKEYs[] = {
5220 "alter table pgbench_tellers add constraint pgbench_tellers_bid_fkey foreign key (bid) references pgbench_branches",
5221 "alter table pgbench_accounts add constraint pgbench_accounts_bid_fkey foreign key (bid) references pgbench_branches",
5222 "alter table pgbench_history add constraint pgbench_history_bid_fkey foreign key (bid) references pgbench_branches",
5223 "alter table pgbench_history add constraint pgbench_history_tid_fkey foreign key (tid) references pgbench_tellers",
5224 "alter table pgbench_history add constraint pgbench_history_aid_fkey foreign key (aid) references pgbench_accounts"
5225 };
5226 int i;
5227
5228 fprintf(stderr, "creating foreign keys...\n");
5229 for (i = 0; i < lengthof(DDLKEYs); i++)
5230 {
5231 executeStatement(con, DDLKEYs[i]);
5232 }
5233}
5234
5235/*
5236 * Validate an initialization-steps string
5237 *
5238 * (We could just leave it to runInitSteps() to fail if there are wrong
5239 * characters, but since initialization can take awhile, it seems friendlier
5240 * to check during option parsing.)
5241 */
5242static void
5243checkInitSteps(const char *initialize_steps)
5244{
5245 if (initialize_steps[0] == '\0')
5246 pg_fatal("no initialization steps specified");
5247
5248 for (const char *step = initialize_steps; *step != '\0'; step++)
5249 {
5250 if (strchr(ALL_INIT_STEPS " ", *step) == NULL)
5251 {
5252 pg_log_error("unrecognized initialization step \"%c\"", *step);
5253 pg_log_error_detail("Allowed step characters are: \"" ALL_INIT_STEPS "\".");
5254 exit(1);
5255 }
5256 }
5257}
5258
5259/*
5260 * Invoke each initialization step in the given string
5261 */
5262static void
5263runInitSteps(const char *initialize_steps)
5264{
5265 PQExpBufferData stats;
5266 PGconn *con;
5267 const char *step;
5268 double run_time = 0.0;
5269 bool first = true;
5270
5271 initPQExpBuffer(&stats);
5272
5273 if ((con = doConnect()) == NULL)
5274 pg_fatal("could not create connection for initialization");
5275
5277 SetCancelConn(con);
5278
5279 for (step = initialize_steps; *step != '\0'; step++)
5280 {
5281 char *op = NULL;
5283
5284 switch (*step)
5285 {
5286 case 'd':
5287 op = "drop tables";
5288 initDropTables(con);
5289 break;
5290 case 't':
5291 op = "create tables";
5292 initCreateTables(con);
5293 break;
5294 case 'g':
5295 op = "client-side generate";
5297 break;
5298 case 'G':
5299 op = "server-side generate";
5301 break;
5302 case 'v':
5303 op = "vacuum";
5304 initVacuum(con);
5305 break;
5306 case 'p':
5307 op = "primary keys";
5308 initCreatePKeys(con);
5309 break;
5310 case 'f':
5311 op = "foreign keys";
5312 initCreateFKeys(con);
5313 break;
5314 case ' ':
5315 break; /* ignore */
5316 default:
5317 pg_log_error("unrecognized initialization step \"%c\"", *step);
5318 PQfinish(con);
5319 exit(1);
5320 }
5321
5322 if (op != NULL)
5323 {
5324 double elapsed_sec = PG_TIME_GET_DOUBLE(pg_time_now() - start);
5325
5326 if (!first)
5327 appendPQExpBufferStr(&stats, ", ");
5328 else
5329 first = false;
5330
5331 appendPQExpBuffer(&stats, "%s %.2f s", op, elapsed_sec);
5332
5333 run_time += elapsed_sec;
5334 }
5335 }
5336
5337 fprintf(stderr, "done in %.2f s (%s).\n", run_time, stats.data);
5339 PQfinish(con);
5340 termPQExpBuffer(&stats);
5341}
5342
5343/*
5344 * Extract pgbench table information into global variables scale,
5345 * partition_method and partitions.
5346 */
5347static void
5348GetTableInfo(PGconn *con, bool scale_given)
5349{
5350 PGresult *res;
5351
5352 /*
5353 * get the scaling factor that should be same as count(*) from
5354 * pgbench_branches if this is not a custom query
5355 */
5356 res = PQexec(con, "select count(*) from pgbench_branches");
5357 if (PQresultStatus(res) != PGRES_TUPLES_OK)
5358 {
5359 char *sqlState = PQresultErrorField(res, PG_DIAG_SQLSTATE);
5360
5361 pg_log_error("could not count number of branches: %s", PQerrorMessage(con));
5362
5363 if (sqlState && strcmp(sqlState, ERRCODE_UNDEFINED_TABLE) == 0)
5364 pg_log_error_hint("Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".",
5365 PQdb(con));
5366
5367 exit(1);
5368 }
5369 scale = atoi(PQgetvalue(res, 0, 0));
5370 if (scale < 0)
5371 pg_fatal("invalid count(*) from pgbench_branches: \"%s\"",
5372 PQgetvalue(res, 0, 0));
5373 PQclear(res);
5374
5375 /* warn if we override user-given -s switch */
5376 if (scale_given)
5377 pg_log_warning("scale option ignored, using count from pgbench_branches table (%d)",
5378 scale);
5379
5380 /*
5381 * Get the partition information for the first "pgbench_accounts" table
5382 * found in search_path.
5383 *
5384 * The result is empty if no "pgbench_accounts" is found.
5385 *
5386 * Otherwise, it always returns one row even if the table is not
5387 * partitioned (in which case the partition strategy is NULL).
5388 *
5389 * The number of partitions can be 0 even for partitioned tables, if no
5390 * partition is attached.
5391 *
5392 * We assume no partitioning on any failure, so as to avoid failing on an
5393 * old version without "pg_partitioned_table".
5394 */
5395 res = PQexec(con,
5396 "select o.n, p.partstrat, pg_catalog.count(i.inhparent) "
5397 "from pg_catalog.pg_class as c "
5398 "join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) "
5399 "cross join lateral (select pg_catalog.array_position(pg_catalog.current_schemas(true), n.nspname)) as o(n) "
5400 "left join pg_catalog.pg_partitioned_table as p on (p.partrelid = c.oid) "
5401 "left join pg_catalog.pg_inherits as i on (c.oid = i.inhparent) "
5402 "where c.relname = 'pgbench_accounts' and o.n is not null "
5403 "group by 1, 2 "
5404 "order by 1 asc "
5405 "limit 1");
5406
5407 if (PQresultStatus(res) != PGRES_TUPLES_OK)
5408 {
5409 /* probably an older version, coldly assume no partitioning */
5411 partitions = 0;
5412 }
5413 else if (PQntuples(res) == 0)
5414 {
5415 /*
5416 * This case is unlikely as pgbench already found "pgbench_branches"
5417 * above to compute the scale.
5418 */
5419 pg_log_error("no pgbench_accounts table found in \"search_path\"");
5420 pg_log_error_hint("Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".", PQdb(con));
5421 exit(1);
5422 }
5423 else /* PQntuples(res) == 1 */
5424 {
5425 /* normal case, extract partition information */
5426 if (PQgetisnull(res, 0, 1))
5428 else
5429 {
5430 char *ps = PQgetvalue(res, 0, 1);
5431
5432 /* column must be there */
5433 Assert(ps != NULL);
5434
5435 if (strcmp(ps, "r") == 0)
5437 else if (strcmp(ps, "h") == 0)
5439 else
5440 {
5441 /* possibly a newer version with new partition method */
5442 pg_fatal("unexpected partition method: \"%s\"", ps);
5443 }
5444 }
5445
5446 partitions = atoi(PQgetvalue(res, 0, 2));
5447 }
5448
5449 PQclear(res);
5450}
5451
5452/*
5453 * Replace :param with $n throughout the command's SQL text, which
5454 * is a modifiable string in cmd->lines.
5455 */
5456static bool
5457parseQuery(Command *cmd)
5458{
5459 char *sql,
5460 *p;
5461
5462 cmd->argc = 1;
5463
5464 p = sql = pg_strdup(cmd->lines.data);
5465 while ((p = strchr(p, ':')) != NULL)
5466 {
5467 char var[13];
5468 char *name;
5469 int eaten;
5470
5471 name = parseVariable(p, &eaten);
5472 if (name == NULL)
5473 {
5474 while (*p == ':')
5475 {
5476 p++;
5477 }
5478 continue;
5479 }
5480
5481 /*
5482 * cmd->argv[0] is the SQL statement itself, so the max number of
5483 * arguments is one less than MAX_ARGS
5484 */
5485 if (cmd->argc >= MAX_ARGS)
5486 {
5487 pg_log_error("statement has too many arguments (maximum is %d): %s",
5488 MAX_ARGS - 1, cmd->lines.data);
5489 pg_free(name);
5490 return false;
5491 }
5492
5493 sprintf(var, "$%d", cmd->argc);
5494 p = replaceVariable(&sql, p, eaten, var);
5495
5496 cmd->argv[cmd->argc] = name;
5497 cmd->argc++;
5498 }
5499
5500 Assert(cmd->argv[0] == NULL);
5501 cmd->argv[0] = sql;
5502 return true;
5503}
5504
5505/*
5506 * syntax error while parsing a script (in practice, while parsing a
5507 * backslash command, because we don't detect syntax errors in SQL)
5508 *
5509 * source: source of script (filename or builtin-script ID)
5510 * lineno: line number within script (count from 1)
5511 * line: whole line of backslash command, if available
5512 * command: backslash command name, if available
5513 * msg: the actual error message
5514 * more: optional extra message
5515 * column: zero-based column number, or -1 if unknown
5516 */
5517void
5518syntax_error(const char *source, int lineno,
5519 const char *line, const char *command,
5520 const char *msg, const char *more, int column)
5521{
5523
5525
5526 printfPQExpBuffer(&buf, "%s:%d: %s", source, lineno, msg);
5527 if (more != NULL)
5528 appendPQExpBuffer(&buf, " (%s)", more);
5529 if (column >= 0 && line == NULL)
5530 appendPQExpBuffer(&buf, " at column %d", column + 1);
5531 if (command != NULL)
5532 appendPQExpBuffer(&buf, " in command \"%s\"", command);
5533
5534 pg_log_error("%s", buf.data);
5535
5537
5538 if (line != NULL)
5539 {
5540 fprintf(stderr, "%s\n", line);
5541 if (column >= 0)
5542 fprintf(stderr, "%*c error found here\n", column + 1, '^');
5543 }
5544
5545 exit(1);
5546}
5547
5548/*
5549 * Return a pointer to the start of the SQL command, after skipping over
5550 * whitespace and "--" comments.
5551 * If the end of the string is reached, return NULL.
5552 */
5553static char *
5554skip_sql_comments(char *sql_command)
5555{
5556 char *p = sql_command;
5557
5558 /* Skip any leading whitespace, as well as "--" style comments */
5559 for (;;)
5560 {
5561 if (isspace((unsigned char) *p))
5562 p++;
5563 else if (strncmp(p, "--", 2) == 0)
5564 {
5565 p = strchr(p, '\n');
5566 if (p == NULL)
5567 return NULL;
5568 p++;
5569 }
5570 else
5571 break;
5572 }
5573
5574 /* NULL if there's nothing but whitespace and comments */
5575 if (*p == '\0')
5576 return NULL;
5577
5578 return p;
5579}
5580
5581/*
5582 * Parse a SQL command; return a Command struct, or NULL if it's a comment
5583 *
5584 * On entry, psqlscan.l has collected the command into "buf", so we don't
5585 * really need to do much here except check for comments and set up a Command
5586 * struct.
5587 */
5588static Command *
5590{
5591 Command *my_command;
5592 char *p = skip_sql_comments(buf->data);
5593
5594 if (p == NULL)
5595 return NULL;
5596
5597 /* Allocate and initialize Command structure */
5598 my_command = (Command *) pg_malloc(sizeof(Command));
5599 initPQExpBuffer(&my_command->lines);
5600 appendPQExpBufferStr(&my_command->lines, p);
5601 my_command->first_line = NULL; /* this is set later */
5602 my_command->type = SQL_COMMAND;
5603 my_command->meta = META_NONE;
5604 my_command->argc = 0;
5605 my_command->retries = 0;
5606 my_command->failures = 0;
5607 memset(my_command->argv, 0, sizeof(my_command->argv));
5608 my_command->varprefix = NULL; /* allocated later, if needed */
5609 my_command->expr = NULL;
5610 initSimpleStats(&my_command->stats);
5611 my_command->prepname = NULL; /* set later, if needed */
5612
5613 return my_command;
5614}
5615
5616/* Free a Command structure and associated data */
5617static void
5618free_command(Command *command)
5619{
5620 termPQExpBuffer(&command->lines);
5621 pg_free(command->first_line);
5622 for (int i = 0; i < command->argc; i++)
5623 pg_free(command->argv[i]);
5624 pg_free(command->varprefix);
5625
5626 /*
5627 * It should also free expr recursively, but this is currently not needed
5628 * as only gset commands (which do not have an expression) are freed.
5629 */
5630 pg_free(command);
5631}
5632
5633/*
5634 * Once an SQL command is fully parsed, possibly by accumulating several
5635 * parts, complete other fields of the Command structure.
5636 */
5637static void
5639{
5640 char buffer[128];
5641 static int prepnum = 0;
5642
5643 Assert(my_command->type == SQL_COMMAND);
5644
5645 /* Save the first line for error display. */
5646 strlcpy(buffer, my_command->lines.data, sizeof(buffer));
5647 buffer[strcspn(buffer, "\n\r")] = '\0';
5648 my_command->first_line = pg_strdup(buffer);
5649
5650 /* Parse query and generate prepared statement name, if necessary */
5651 switch (querymode)
5652 {
5653 case QUERY_SIMPLE:
5654 my_command->argv[0] = my_command->lines.data;
5655 my_command->argc++;
5656 break;
5657 case QUERY_PREPARED:
5658 my_command->prepname = psprintf("P_%d", prepnum++);
5659 /* fall through */
5660 case QUERY_EXTENDED:
5661 if (!parseQuery(my_command))
5662 exit(1);
5663 break;
5664 default:
5665 exit(1);
5666 }
5667}
5668
5669/*
5670 * Parse a backslash command; return a Command struct, or NULL if comment
5671 *
5672 * At call, we have scanned only the initial backslash.
5673 */
5674static Command *
5676 int lineno, int start_offset)
5677{
5678 Command *my_command;
5679 PQExpBufferData word_buf;
5680 int word_offset;
5681 int offsets[MAX_ARGS]; /* offsets of argument words */
5682 int j;
5683
5684 initPQExpBuffer(&word_buf);
5685
5686 /* Collect first word of command */
5687 if (!expr_lex_one_word(sstate, &word_buf, &word_offset))
5688 {
5689 termPQExpBuffer(&word_buf);
5690 return NULL;
5691 }
5692
5693 /* Allocate and initialize Command structure */
5694 my_command = (Command *) pg_malloc0(sizeof(Command));
5695 my_command->type = META_COMMAND;
5696 my_command->argc = 0;
5697 initSimpleStats(&my_command->stats);
5698
5699 /* Save first word (command name) */
5700 j = 0;
5701 offsets[j] = word_offset;
5702 my_command->argv[j++] = pg_strdup(word_buf.data);
5703 my_command->argc++;
5704
5705 /* ... and convert it to enum form */
5706 my_command->meta = getMetaCommand(my_command->argv[0]);
5707
5708 if (my_command->meta == META_SET ||
5709 my_command->meta == META_IF ||
5710 my_command->meta == META_ELIF)
5711 {
5712 yyscan_t yyscanner;
5713
5714 /* For \set, collect var name */
5715 if (my_command->meta == META_SET)
5716 {
5717 if (!expr_lex_one_word(sstate, &word_buf, &word_offset))
5718 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5719 "missing argument", NULL, -1);
5720
5721 offsets[j] = word_offset;
5722 my_command->argv[j++] = pg_strdup(word_buf.data);
5723 my_command->argc++;
5724 }
5725
5726 /* then for all parse the expression */
5727 yyscanner = expr_scanner_init(sstate, source, lineno, start_offset,
5728 my_command->argv[0]);
5729
5730 if (expr_yyparse(&my_command->expr, yyscanner) != 0)
5731 {
5732 /* dead code: exit done from syntax_error called by yyerror */
5733 exit(1);
5734 }
5735
5736 /* Save line, trimming any trailing newline */
5737 my_command->first_line =
5739 start_offset,
5740 true);
5741
5742 expr_scanner_finish(yyscanner);
5743
5744 termPQExpBuffer(&word_buf);
5745
5746 return my_command;
5747 }
5748
5749 /* For all other commands, collect remaining words. */
5750 while (expr_lex_one_word(sstate, &word_buf, &word_offset))
5751 {
5752 /*
5753 * my_command->argv[0] is the command itself, so the max number of
5754 * arguments is one less than MAX_ARGS
5755 */
5756 if (j >= MAX_ARGS)
5757 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5758 "too many arguments", NULL, -1);
5759
5760 offsets[j] = word_offset;
5761 my_command->argv[j++] = pg_strdup(word_buf.data);
5762 my_command->argc++;
5763 }
5764
5765 /* Save line, trimming any trailing newline */
5766 my_command->first_line =
5768 start_offset,
5769 true);
5770
5771 if (my_command->meta == META_SLEEP)
5772 {
5773 if (my_command->argc < 2)
5774 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5775 "missing argument", NULL, -1);
5776
5777 if (my_command->argc > 3)
5778 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5779 "too many arguments", NULL,
5780 offsets[3] - start_offset);
5781
5782 /*
5783 * Split argument into number and unit to allow "sleep 1ms" etc. We
5784 * don't have to terminate the number argument with null because it
5785 * will be parsed with atoi, which ignores trailing non-digit
5786 * characters.
5787 */
5788 if (my_command->argv[1][0] != ':')
5789 {
5790 char *c = my_command->argv[1];
5791 bool have_digit = false;
5792
5793 /* Skip sign */
5794 if (*c == '+' || *c == '-')
5795 c++;
5796
5797 /* Require at least one digit */
5798 if (*c && isdigit((unsigned char) *c))
5799 have_digit = true;
5800
5801 /* Eat all digits */
5802 while (*c && isdigit((unsigned char) *c))
5803 c++;
5804
5805 if (*c)
5806 {
5807 if (my_command->argc == 2 && have_digit)
5808 {
5809 my_command->argv[2] = c;
5810 offsets[2] = offsets[1] + (c - my_command->argv[1]);
5811 my_command->argc = 3;
5812 }
5813 else
5814 {
5815 /*
5816 * Raise an error if argument starts with non-digit
5817 * character (after sign).
5818 */
5819 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5820 "invalid sleep time, must be an integer",
5821 my_command->argv[1], offsets[1] - start_offset);
5822 }
5823 }
5824 }
5825
5826 if (my_command->argc == 3)
5827 {
5828 if (pg_strcasecmp(my_command->argv[2], "us") != 0 &&
5829 pg_strcasecmp(my_command->argv[2], "ms") != 0 &&
5830 pg_strcasecmp(my_command->argv[2], "s") != 0)
5831 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5832 "unrecognized time unit, must be us, ms or s",
5833 my_command->argv[2], offsets[2] - start_offset);
5834 }
5835 }
5836 else if (my_command->meta == META_SETSHELL)
5837 {
5838 if (my_command->argc < 3)
5839 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5840 "missing argument", NULL, -1);
5841 }
5842 else if (my_command->meta == META_SHELL)
5843 {
5844 if (my_command->argc < 2)
5845 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5846 "missing command", NULL, -1);
5847 }
5848 else if (my_command->meta == META_ELSE || my_command->meta == META_ENDIF ||
5849 my_command->meta == META_STARTPIPELINE ||
5850 my_command->meta == META_ENDPIPELINE ||
5851 my_command->meta == META_SYNCPIPELINE)
5852 {
5853 if (my_command->argc != 1)
5854 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5855 "unexpected argument", NULL, -1);
5856 }
5857 else if (my_command->meta == META_GSET || my_command->meta == META_ASET)
5858 {
5859 if (my_command->argc > 2)
5860 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5861 "too many arguments", NULL, -1);
5862 }
5863 else
5864 {
5865 /* my_command->meta == META_NONE */
5866 syntax_error(source, lineno, my_command->first_line, my_command->argv[0],
5867 "invalid command", NULL, -1);
5868 }
5869
5870 termPQExpBuffer(&word_buf);
5871
5872 return my_command;
5873}
5874
5875static void
5876ConditionError(const char *desc, int cmdn, const char *msg)
5877{
5878 pg_fatal("condition error in script \"%s\" command %d: %s",
5879 desc, cmdn, msg);
5880}
5881
5882/*
5883 * Partial evaluation of conditionals before recording and running the script.
5884 */
5885static void
5887{
5888 /* statically check conditional structure */
5890 int i;
5891
5892 for (i = 0; ps->commands[i] != NULL; i++)
5893 {
5894 Command *cmd = ps->commands[i];
5895
5896 if (cmd->type == META_COMMAND)
5897 {
5898 switch (cmd->meta)
5899 {
5900 case META_IF:
5902 break;
5903 case META_ELIF:
5905 ConditionError(ps->desc, i + 1, "\\elif without matching \\if");
5907 ConditionError(ps->desc, i + 1, "\\elif after \\else");
5908 break;
5909 case META_ELSE:
5911 ConditionError(ps->desc, i + 1, "\\else without matching \\if");
5913 ConditionError(ps->desc, i + 1, "\\else after \\else");
5915 break;
5916 case META_ENDIF:
5917 if (!conditional_stack_pop(cs))
5918 ConditionError(ps->desc, i + 1, "\\endif without matching \\if");
5919 break;
5920 default:
5921 /* ignore anything else... */
5922 break;
5923 }
5924 }
5925 }
5926 if (!conditional_stack_empty(cs))
5927 ConditionError(ps->desc, i + 1, "\\if without matching \\endif");
5929}
5930
5931/*
5932 * Parse a script (either the contents of a file, or a built-in script)
5933 * and add it to the list of scripts.
5934 */
5935static void
5936ParseScript(const char *script, const char *desc, int weight)
5937{
5939 PsqlScanState sstate;
5940 PQExpBufferData line_buf;
5941 int alloc_num;
5942 int index;
5943
5944#define COMMANDS_ALLOC_NUM 128
5945 alloc_num = COMMANDS_ALLOC_NUM;
5946
5947 /* Initialize all fields of ps */
5948 ps.desc = desc;
5949 ps.weight = weight;
5950 ps.commands = (Command **) pg_malloc(sizeof(Command *) * alloc_num);
5951 initStats(&ps.stats, 0);
5952
5953 /* Prepare to parse script */
5955
5956 /*
5957 * Ideally, we'd scan scripts using the encoding and stdstrings settings
5958 * we get from a DB connection. However, without major rearrangement of
5959 * pgbench's argument parsing, we can't have a DB connection at the time
5960 * we parse scripts. Using SQL_ASCII (encoding 0) should work well enough
5961 * with any backend-safe encoding, though conceivably we could be fooled
5962 * if a script file uses a client-only encoding. We also assume that
5963 * stdstrings should be true, which is a bit riskier.
5964 */
5965 psql_scan_setup(sstate, script, strlen(script), 0, true);
5966
5967 initPQExpBuffer(&line_buf);
5968
5969 index = 0;
5970
5971 for (;;)
5972 {
5973 PsqlScanResult sr;
5974 promptStatus_t prompt;
5975 Command *command = NULL;
5976
5977 resetPQExpBuffer(&line_buf);
5978
5979 sr = psql_scan(sstate, &line_buf, &prompt);
5980
5981 /* If we collected a new SQL command, process that */
5982 command = create_sql_command(&line_buf, desc);
5983
5984 /* store new command */
5985 if (command)
5986 ps.commands[index++] = command;
5987
5988 /* If we reached a backslash, process that */
5989 if (sr == PSCAN_BACKSLASH)
5990 {
5991 int lineno;
5992 int start_offset;
5993
5994 /* Capture location of the backslash */
5995 psql_scan_get_location(sstate, &lineno, &start_offset);
5996 start_offset--;
5997
5998 command = process_backslash_command(sstate, desc,
5999 lineno, start_offset);
6000
6001 if (command)
6002 {
6003 /*
6004 * If this is gset or aset, merge into the preceding command.
6005 * (We don't use a command slot in this case).
6006 */
6007 if (command->meta == META_GSET || command->meta == META_ASET)
6008 {
6009 Command *cmd;
6010
6011 if (index == 0)
6012 syntax_error(desc, lineno, NULL, NULL,
6013 "\\gset must follow an SQL command",
6014 NULL, -1);
6015
6016 cmd = ps.commands[index - 1];
6017
6018 if (cmd->type != SQL_COMMAND ||
6019 cmd->varprefix != NULL)
6020 syntax_error(desc, lineno, NULL, NULL,
6021 "\\gset must follow an SQL command",
6022 cmd->first_line, -1);
6023
6024 /* get variable prefix */
6025 if (command->argc <= 1 || command->argv[1][0] == '\0')
6026 cmd->varprefix = pg_strdup("");
6027 else
6028 cmd->varprefix = pg_strdup(command->argv[1]);
6029
6030 /* update the sql command meta */
6031 cmd->meta = command->meta;
6032
6033 /* cleanup unused command */
6034 free_command(command);
6035
6036 continue;
6037 }
6038
6039 /* Attach any other backslash command as a new command */
6040 ps.commands[index++] = command;
6041 }
6042 }
6043
6044 /*
6045 * Since we used a command slot, allocate more if needed. Note we
6046 * always allocate one more in order to accommodate the NULL
6047 * terminator below.
6048 */
6049 if (index >= alloc_num)
6050 {
6051 alloc_num += COMMANDS_ALLOC_NUM;
6052 ps.commands = (Command **)
6053 pg_realloc(ps.commands, sizeof(Command *) * alloc_num);
6054 }
6055
6056 /* Done if we reached EOF */
6057 if (sr == PSCAN_INCOMPLETE || sr == PSCAN_EOL)
6058 break;
6059 }
6060
6061 ps.commands[index] = NULL;
6062
6063 addScript(&ps);
6064
6065 termPQExpBuffer(&line_buf);
6066 psql_scan_finish(sstate);
6067 psql_scan_destroy(sstate);
6068}
6069
6070/*
6071 * Read the entire contents of file fd, and return it in a malloc'd buffer.
6072 *
6073 * The buffer will typically be larger than necessary, but we don't care
6074 * in this program, because we'll free it as soon as we've parsed the script.
6075 */
6076static char *
6078{
6079 char *buf;
6080 size_t buflen = BUFSIZ;
6081 size_t used = 0;
6082
6083 buf = (char *) pg_malloc(buflen);
6084
6085 for (;;)
6086 {
6087 size_t nread;
6088
6089 nread = fread(buf + used, 1, BUFSIZ, fd);
6090 used += nread;
6091 /* If fread() read less than requested, must be EOF or error */
6092 if (nread < BUFSIZ)
6093 break;
6094 /* Enlarge buf so we can read some more */
6095 buflen += BUFSIZ;
6096 buf = (char *) pg_realloc(buf, buflen);
6097 }
6098 /* There is surely room for a terminator */
6099 buf[used] = '\0';
6100
6101 return buf;
6102}
6103
6104/*
6105 * Given a file name, read it and add its script to the list.
6106 * "-" means to read stdin.
6107 * NB: filename must be storage that won't disappear.
6108 */
6109static void
6110process_file(const char *filename, int weight)
6111{
6112 FILE *fd;
6113 char *buf;
6114
6115 /* Slurp the file contents into "buf" */
6116 if (strcmp(filename, "-") == 0)
6117 fd = stdin;
6118 else if ((fd = fopen(filename, "r")) == NULL)
6119 pg_fatal("could not open file \"%s\": %m", filename);
6120
6122
6123 if (ferror(fd))
6124 pg_fatal("could not read file \"%s\": %m", filename);
6125
6126 if (fd != stdin)
6127 fclose(fd);
6128
6129 ParseScript(buf, filename, weight);
6130
6131 free(buf);
6132}
6133
6134/* Parse the given builtin script and add it to the list. */
6135static void
6136process_builtin(const BuiltinScript *bi, int weight)
6137{
6138 ParseScript(bi->script, bi->desc, weight);
6139}
6140
6141/* show available builtin scripts */
6142static void
6144{
6145 int i;
6146
6147 fprintf(stderr, "Available builtin scripts:\n");
6148 for (i = 0; i < lengthof(builtin_script); i++)
6149 fprintf(stderr, " %13s: %s\n", builtin_script[i].name, builtin_script[i].desc);
6150 fprintf(stderr, "\n");
6151}
6152
6153/* return builtin script "name" if unambiguous, fails if not found */
6154static const BuiltinScript *
6155findBuiltin(const char *name)
6156{
6157 int i,
6158 found = 0,
6159 len = strlen(name);
6160 const BuiltinScript *result = NULL;
6161
6162 for (i = 0; i < lengthof(builtin_script); i++)
6163 {
6164 if (strncmp(builtin_script[i].name, name, len) == 0)
6165 {
6166 result = &builtin_script[i];
6167 found++;
6168 }
6169 }
6170
6171 /* ok, unambiguous result */
6172 if (found == 1)
6173 return result;
6174
6175 /* error cases */
6176 if (found == 0)
6177 pg_log_error("no builtin script found for name \"%s\"", name);
6178 else /* found > 1 */
6179 pg_log_error("ambiguous builtin name: %d builtin scripts found for prefix \"%s\"", found, name);
6180
6182 exit(1);
6183}
6184
6185/*
6186 * Determine the weight specification from a script option (-b, -f), if any,
6187 * and return it as an integer (1 is returned if there's no weight). The
6188 * script name is returned in *script as a malloc'd string.
6189 */
6190static int
6191parseScriptWeight(const char *option, char **script)
6192{
6193 char *sep;
6194 int weight;
6195
6196 if ((sep = strrchr(option, WSEP)))
6197 {
6198 int namelen = sep - option;
6199 long wtmp;
6200 char *badp;
6201
6202 /* generate the script name */
6203 *script = pg_malloc(namelen + 1);
6204 strncpy(*script, option, namelen);
6205 (*script)[namelen] = '\0';
6206
6207 /* process digits of the weight spec */
6208 errno = 0;
6209 wtmp = strtol(sep + 1, &badp, 10);
6210 if (errno != 0 || badp == sep + 1 || *badp != '\0')
6211 pg_fatal("invalid weight specification: %s", sep);
6212 if (wtmp > INT_MAX || wtmp < 0)
6213 pg_fatal("weight specification out of range (0 .. %d): %lld",
6214 INT_MAX, (long long) wtmp);
6215 weight = wtmp;
6216 }
6217 else
6218 {
6219 *script = pg_strdup(option);
6220 weight = 1;
6221 }
6222
6223 return weight;
6224}
6225
6226/* append a script to the list of scripts to process */
6227static void
6228addScript(const ParsedScript *script)
6229{
6230 if (script->commands == NULL || script->commands[0] == NULL)
6231 pg_fatal("empty command list for script \"%s\"", script->desc);
6232
6233 if (num_scripts >= MAX_SCRIPTS)
6234 pg_fatal("at most %d SQL scripts are allowed", MAX_SCRIPTS);
6235
6236 CheckConditional(script);
6237
6238 sql_script[num_scripts] = *script;
6239 num_scripts++;
6240}
6241
6242/*
6243 * Print progress report.
6244 *
6245 * On entry, *last and *last_report contain the statistics and time of last
6246 * progress report. On exit, they are updated with the new stats.
6247 */
6248static void
6249printProgressReport(TState *threads, int64 test_start, pg_time_usec_t now,
6250 StatsData *last, int64 *last_report)
6251{
6252 /* generate and show report */
6253 pg_time_usec_t run = now - *last_report;
6254 int64 cnt,
6255 failures,
6256 retried;
6257 double tps,
6258 total_run,
6259 latency,
6260 sqlat,
6261 lag,
6262 stdev;
6263 char tbuf[315];
6264 StatsData cur;
6265
6266 /*
6267 * Add up the statistics of all threads.
6268 *
6269 * XXX: No locking. There is no guarantee that we get an atomic snapshot
6270 * of the transaction count and latencies, so these figures can well be
6271 * off by a small amount. The progress report's purpose is to give a
6272 * quick overview of how the test is going, so that shouldn't matter too
6273 * much. (If a read from a 64-bit integer is not atomic, you might get a
6274 * "torn" read and completely bogus latencies though!)
6275 */
6276 initStats(&cur, 0);
6277 for (int i = 0; i < nthreads; i++)
6278 {
6279 mergeSimpleStats(&cur.latency, &threads[i].stats.latency);
6280 mergeSimpleStats(&cur.lag, &threads[i].stats.lag);
6281 cur.cnt += threads[i].stats.cnt;
6282 cur.skipped += threads[i].stats.skipped;
6283 cur.retries += threads[i].stats.retries;
6284 cur.retried += threads[i].stats.retried;
6285 cur.serialization_failures +=
6287 cur.deadlock_failures += threads[i].stats.deadlock_failures;
6288 }
6289
6290 /* we count only actually executed transactions */
6291 cnt = cur.cnt - last->cnt;
6292 total_run = (now - test_start) / 1000000.0;
6293 tps = 1000000.0 * cnt / run;
6294 if (cnt > 0)
6295 {
6296 latency = 0.001 * (cur.latency.sum - last->latency.sum) / cnt;
6297 sqlat = 1.0 * (cur.latency.sum2 - last->latency.sum2) / cnt;
6298 stdev = 0.001 * sqrt(sqlat - 1000000.0 * latency * latency);
6299 lag = 0.001 * (cur.lag.sum - last->lag.sum) / cnt;
6300 }
6301 else
6302 {
6303 latency = sqlat = stdev = lag = 0;
6304 }
6305 failures = getFailures(&cur) - getFailures(last);
6306 retried = cur.retried - last->retried;
6307
6309 {
6310 snprintf(tbuf, sizeof(tbuf), "%.3f s",
6312 }
6313 else
6314 {
6315 /* round seconds are expected, but the thread may be late */
6316 snprintf(tbuf, sizeof(tbuf), "%.1f s", total_run);
6317 }
6318
6319 fprintf(stderr,
6320 "progress: %s, %.1f tps, lat %.3f ms stddev %.3f, " INT64_FORMAT " failed",
6321 tbuf, tps, latency, stdev, failures);
6322
6323 if (throttle_delay)
6324 {
6325 fprintf(stderr, ", lag %.3f ms", lag);
6326 if (latency_limit)
6327 fprintf(stderr, ", " INT64_FORMAT " skipped",
6328 cur.skipped - last->skipped);
6329 }
6330
6331 /* it can be non-zero only if max_tries is not equal to one */
6332 if (max_tries != 1)
6333 fprintf(stderr,
6334 ", " INT64_FORMAT " retried, " INT64_FORMAT " retries",
6335 retried, cur.retries - last->retries);
6336 fprintf(stderr, "\n");
6337
6338 *last = cur;
6339 *last_report = now;
6340}
6341
6342static void
6343printSimpleStats(const char *prefix, SimpleStats *ss)
6344{
6345 if (ss->count > 0)
6346 {
6347 double latency = ss->sum / ss->count;
6348 double stddev = sqrt(ss->sum2 / ss->count - latency * latency);
6349
6350 printf("%s average = %.3f ms\n", prefix, 0.001 * latency);
6351 printf("%s stddev = %.3f ms\n", prefix, 0.001 * stddev);
6352 }
6353}
6354
6355/* print version banner */
6356static void
6357printVersion(PGconn *con)
6358{
6359 int server_ver = PQserverVersion(con);
6360 int client_ver = PG_VERSION_NUM;
6361
6362 if (server_ver != client_ver)
6363 {
6364 const char *server_version;
6365 char sverbuf[32];
6366
6367 /* Try to get full text form, might include "devel" etc */
6368 server_version = PQparameterStatus(con, "server_version");
6369 /* Otherwise fall back on server_ver */
6370 if (!server_version)
6371 {
6372 formatPGVersionNumber(server_ver, true,
6373 sverbuf, sizeof(sverbuf));
6374 server_version = sverbuf;
6375 }
6376
6377 printf(_("%s (%s, server %s)\n"),
6378 "pgbench", PG_VERSION, server_version);
6379 }
6380 /* For version match, only print pgbench version */
6381 else
6382 printf("%s (%s)\n", "pgbench", PG_VERSION);
6383 fflush(stdout);
6384}
6385
6386/* print out results */
6387static void
6388printResults(StatsData *total,
6389 pg_time_usec_t total_duration, /* benchmarking time */
6390 pg_time_usec_t conn_total_duration, /* is_connect */
6391 pg_time_usec_t conn_elapsed_duration, /* !is_connect */
6392 int64 latency_late)
6393{
6394 /* tps is about actually executed transactions during benchmarking */
6395 int64 failures = getFailures(total);
6396 int64 total_cnt = total->cnt + total->skipped + failures;
6397 double bench_duration = PG_TIME_GET_DOUBLE(total_duration);
6398 double tps = total->cnt / bench_duration;
6399
6400 /* Report test parameters. */
6401 printf("transaction type: %s\n",
6402 num_scripts == 1 ? sql_script[0].desc : "multiple scripts");
6403 printf("scaling factor: %d\n", scale);
6404 /* only print partitioning information if some partitioning was detected */
6406 printf("partition method: %s\npartitions: %d\n",
6408 printf("query mode: %s\n", QUERYMODE[querymode]);
6409 printf("number of clients: %d\n", nclients);
6410 printf("number of threads: %d\n", nthreads);
6411
6412 if (max_tries)
6413 printf("maximum number of tries: %u\n", max_tries);
6414
6415 if (duration <= 0)
6416 {
6417 printf("number of transactions per client: %d\n", nxacts);
6418 printf("number of transactions actually processed: " INT64_FORMAT "/%d\n",
6419 total->cnt, nxacts * nclients);
6420 }
6421 else
6422 {
6423 printf("duration: %d s\n", duration);
6424 printf("number of transactions actually processed: " INT64_FORMAT "\n",
6425 total->cnt);
6426 }
6427
6428 /*
6429 * Remaining stats are nonsensical if we failed to execute any xacts due
6430 * to others than serialization or deadlock errors
6431 */
6432 if (total_cnt <= 0)
6433 return;
6434
6435 printf("number of failed transactions: " INT64_FORMAT " (%.3f%%)\n",
6436 failures, 100.0 * failures / total_cnt);
6437
6439 {
6440 printf("number of serialization failures: " INT64_FORMAT " (%.3f%%)\n",
6442 100.0 * total->serialization_failures / total_cnt);
6443 printf("number of deadlock failures: " INT64_FORMAT " (%.3f%%)\n",
6444 total->deadlock_failures,
6445 100.0 * total->deadlock_failures / total_cnt);
6446 }
6447
6448 /* it can be non-zero only if max_tries is not equal to one */
6449 if (max_tries != 1)
6450 {
6451 printf("number of transactions retried: " INT64_FORMAT " (%.3f%%)\n",
6452 total->retried, 100.0 * total->retried / total_cnt);
6453 printf("total number of retries: " INT64_FORMAT "\n", total->retries);
6454 }
6455
6457 printf("number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n",
6458 total->skipped, 100.0 * total->skipped / total_cnt);
6459
6460 if (latency_limit)
6461 printf("number of transactions above the %.1f ms latency limit: " INT64_FORMAT "/" INT64_FORMAT " (%.3f%%)\n",
6462 latency_limit / 1000.0, latency_late, total->cnt,
6463 (total->cnt > 0) ? 100.0 * latency_late / total->cnt : 0.0);
6464
6466 printSimpleStats("latency", &total->latency);
6467 else
6468 {
6469 /* no measurement, show average latency computed from run time */
6470 printf("latency average = %.3f ms%s\n",
6471 0.001 * total_duration * nclients / total_cnt,
6472 failures > 0 ? " (including failures)" : "");
6473 }
6474
6475 if (throttle_delay)
6476 {
6477 /*
6478 * Report average transaction lag under rate limit throttling. This
6479 * is the delay between scheduled and actual start times for the
6480 * transaction. The measured lag may be caused by thread/client load,
6481 * the database load, or the Poisson throttling process.
6482 */
6483 printf("rate limit schedule lag: avg %.3f (max %.3f) ms\n",
6484 0.001 * total->lag.sum / total->cnt, 0.001 * total->lag.max);
6485 }
6486
6487 /*
6488 * Under -C/--connect, each transaction incurs a significant connection
6489 * cost, it would not make much sense to ignore it in tps, and it would
6490 * not be tps anyway.
6491 *
6492 * Otherwise connections are made just once at the beginning of the run
6493 * and should not impact performance but for very short run, so they are
6494 * (right)fully ignored in tps.
6495 */
6496 if (is_connect)
6497 {
6498 printf("average connection time = %.3f ms\n", 0.001 * conn_total_duration / (total->cnt + failures));
6499 printf("tps = %f (including reconnection times)\n", tps);
6500 }
6501 else
6502 {
6503 printf("initial connection time = %.3f ms\n", 0.001 * conn_elapsed_duration);
6504 printf("tps = %f (without initial connection time)\n", tps);
6505 }
6506
6507 /* Report per-script/command statistics */
6509 {
6510 int i;
6511
6512 for (i = 0; i < num_scripts; i++)
6513 {
6514 if (per_script_stats)
6515 {
6516 StatsData *sstats = &sql_script[i].stats;
6517 int64 script_failures = getFailures(sstats);
6518 int64 script_total_cnt =
6519 sstats->cnt + sstats->skipped + script_failures;
6520
6521 printf("SQL script %d: %s\n"
6522 " - weight: %d (targets %.1f%% of total)\n"
6523 " - " INT64_FORMAT " transactions (%.1f%% of total)\n",
6524 i + 1, sql_script[i].desc,
6525 sql_script[i].weight,
6526 100.0 * sql_script[i].weight / total_weight,
6527 script_total_cnt,
6528 100.0 * script_total_cnt / total_cnt);
6529
6530 if (script_total_cnt > 0)
6531 {
6532 printf(" - number of transactions actually processed: " INT64_FORMAT " (tps = %f)\n",
6533 sstats->cnt, sstats->cnt / bench_duration);
6534
6535 printf(" - number of failed transactions: " INT64_FORMAT " (%.3f%%)\n",
6536 script_failures,
6537 100.0 * script_failures / script_total_cnt);
6538
6540 {
6541 printf(" - number of serialization failures: " INT64_FORMAT " (%.3f%%)\n",
6542 sstats->serialization_failures,
6543 (100.0 * sstats->serialization_failures /
6544 script_total_cnt));
6545 printf(" - number of deadlock failures: " INT64_FORMAT " (%.3f%%)\n",
6546 sstats->deadlock_failures,
6547 (100.0 * sstats->deadlock_failures /
6548 script_total_cnt));
6549 }
6550
6551 /*
6552 * it can be non-zero only if max_tries is not equal to
6553 * one
6554 */
6555 if (max_tries != 1)
6556 {
6557 printf(" - number of transactions retried: " INT64_FORMAT " (%.3f%%)\n",
6558 sstats->retried,
6559 100.0 * sstats->retried / script_total_cnt);
6560 printf(" - total number of retries: " INT64_FORMAT "\n",
6561 sstats->retries);
6562 }
6563
6565 printf(" - number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n",
6566 sstats->skipped,
6567 100.0 * sstats->skipped / script_total_cnt);
6568
6569 }
6570 printSimpleStats(" - latency", &sstats->latency);
6571 }
6572
6573 /*
6574 * Report per-command statistics: latencies, retries after errors,
6575 * failures (errors without retrying).
6576 */
6578 {
6579 Command **commands;
6580
6581 printf("%sstatement latencies in milliseconds%s:\n",
6582 per_script_stats ? " - " : "",
6583 (max_tries == 1 ?
6584 " and failures" :
6585 ", failures and retries"));
6586
6587 for (commands = sql_script[i].commands;
6588 *commands != NULL;
6589 commands++)
6590 {
6591 SimpleStats *cstats = &(*commands)->stats;
6592
6593 if (max_tries == 1)
6594 printf(" %11.3f %10" PRId64 " %s\n",
6595 (cstats->count > 0) ?
6596 1000.0 * cstats->sum / cstats->count : 0.0,
6597 (*commands)->failures,
6598 (*commands)->first_line);
6599 else
6600 printf(" %11.3f %10" PRId64 " %10" PRId64 " %s\n",
6601 (cstats->count > 0) ?
6602 1000.0 * cstats->sum / cstats->count : 0.0,
6603 (*commands)->failures,
6604 (*commands)->retries,
6605 (*commands)->first_line);
6606 }
6607 }
6608 }
6609 }
6610}
6611
6612/*
6613 * Set up a random seed according to seed parameter (NULL means default),
6614 * and initialize base_random_sequence for use in initializing other sequences.
6615 */
6616static bool
6617set_random_seed(const char *seed)
6618{
6619 uint64 iseed;
6620
6621 if (seed == NULL || strcmp(seed, "time") == 0)
6622 {
6623 /* rely on current time */
6624 iseed = pg_time_now();
6625 }
6626 else if (strcmp(seed, "rand") == 0)
6627 {
6628 /* use some "strong" random source */
6629 if (!pg_strong_random(&iseed, sizeof(iseed)))
6630 {
6631 pg_log_error("could not generate random seed");
6632 return false;
6633 }
6634 }
6635 else
6636 {
6637 char garbage;
6638
6639 if (sscanf(seed, "%" SCNu64 "%c", &iseed, &garbage) != 1)
6640 {
6641 pg_log_error("unrecognized random seed option \"%s\"", seed);
6642 pg_log_error_detail("Expecting an unsigned integer, \"time\" or \"rand\".");
6643 return false;
6644 }
6645 }
6646
6647 if (seed != NULL)
6648 pg_log_info("setting random seed to %" PRIu64, iseed);
6649
6650 random_seed = iseed;
6651
6652 /* Initialize base_random_sequence using seed */
6654
6655 return true;
6656}
6657
6659main(int argc, char **argv)
6660{
6661 static struct option long_options[] = {
6662 /* systematic long/short named options */
6663 {"builtin", required_argument, NULL, 'b'},
6664 {"client", required_argument, NULL, 'c'},
6665 {"connect", no_argument, NULL, 'C'},
6666 {"dbname", required_argument, NULL, 'd'},
6667 {"define", required_argument, NULL, 'D'},
6668 {"file", required_argument, NULL, 'f'},
6669 {"fillfactor", required_argument, NULL, 'F'},
6670 {"host", required_argument, NULL, 'h'},
6671 {"initialize", no_argument, NULL, 'i'},
6672 {"init-steps", required_argument, NULL, 'I'},
6673 {"jobs", required_argument, NULL, 'j'},
6674 {"log", no_argument, NULL, 'l'},
6675 {"latency-limit", required_argument, NULL, 'L'},
6676 {"no-vacuum", no_argument, NULL, 'n'},
6677 {"port", required_argument, NULL, 'p'},
6678 {"progress", required_argument, NULL, 'P'},
6679 {"protocol", required_argument, NULL, 'M'},
6680 {"quiet", no_argument, NULL, 'q'},
6681 {"report-per-command", no_argument, NULL, 'r'},
6682 {"rate", required_argument, NULL, 'R'},
6683 {"scale", required_argument, NULL, 's'},
6684 {"select-only", no_argument, NULL, 'S'},
6685 {"skip-some-updates", no_argument, NULL, 'N'},
6686 {"time", required_argument, NULL, 'T'},
6687 {"transactions", required_argument, NULL, 't'},
6688 {"username", required_argument, NULL, 'U'},
6689 {"vacuum-all", no_argument, NULL, 'v'},
6690 /* long-named only options */
6691 {"unlogged-tables", no_argument, NULL, 1},
6692 {"tablespace", required_argument, NULL, 2},
6693 {"index-tablespace", required_argument, NULL, 3},
6694 {"sampling-rate", required_argument, NULL, 4},
6695 {"aggregate-interval", required_argument, NULL, 5},
6696 {"progress-timestamp", no_argument, NULL, 6},
6697 {"log-prefix", required_argument, NULL, 7},
6698 {"foreign-keys", no_argument, NULL, 8},
6699 {"random-seed", required_argument, NULL, 9},
6700 {"show-script", required_argument, NULL, 10},
6701 {"partitions", required_argument, NULL, 11},
6702 {"partition-method", required_argument, NULL, 12},
6703 {"failures-detailed", no_argument, NULL, 13},
6704 {"max-tries", required_argument, NULL, 14},
6705 {"verbose-errors", no_argument, NULL, 15},
6706 {"exit-on-abort", no_argument, NULL, 16},
6707 {"debug", no_argument, NULL, 17},
6708 {NULL, 0, NULL, 0}
6709 };
6710
6711 int c;
6712 bool is_init_mode = false; /* initialize mode? */
6713 char *initialize_steps = NULL;
6714 bool foreign_keys = false;
6715 bool is_no_vacuum = false;
6716 bool do_vacuum_accounts = false; /* vacuum accounts table? */
6717 int optindex;
6718 bool scale_given = false;
6719
6720 bool benchmarking_option_set = false;
6721 bool initialization_option_set = false;
6722 bool internal_script_used = false;
6723
6724 CState *state; /* status of clients */
6725 TState *threads; /* array of thread */
6726
6728 start_time, /* start up time */
6729 bench_start = 0, /* first recorded benchmarking time */
6730 conn_total_duration; /* cumulated connection time in
6731 * threads */
6732 int64 latency_late = 0;
6733 StatsData stats;
6734 int weight;
6735
6736 int i;
6737 int nclients_dealt;
6738
6739#ifdef HAVE_GETRLIMIT
6740 struct rlimit rlim;
6741#endif
6742
6743 PGconn *con;
6744 char *env;
6745
6746 int exit_code = 0;
6747 struct timeval tv;
6748
6749 /*
6750 * Record difference between Unix time and instr_time time. We'll use
6751 * this for logging and aggregation.
6752 */
6753 gettimeofday(&tv, NULL);
6754 epoch_shift = tv.tv_sec * INT64CONST(1000000) + tv.tv_usec - pg_time_now();
6755
6756 pg_logging_init(argv[0]);
6757 progname = get_progname(argv[0]);
6758
6759 if (argc > 1)
6760 {
6761 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
6762 {
6763 usage();
6764 exit(0);
6765 }
6766 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
6767 {
6768 puts("pgbench (PostgreSQL) " PG_VERSION);
6769 exit(0);
6770 }
6771 }
6772
6773 state = (CState *) pg_malloc0(sizeof(CState));
6774
6775 /* set random seed early, because it may be used while parsing scripts. */
6776 if (!set_random_seed(getenv("PGBENCH_RANDOM_SEED")))
6777 pg_fatal("error while setting random seed from PGBENCH_RANDOM_SEED environment variable");
6778
6779 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)
6780 {
6781 char *script;
6782
6783 switch (c)
6784 {
6785 case 'b':
6786 if (strcmp(optarg, "list") == 0)
6787 {
6789 exit(0);
6790 }
6791 weight = parseScriptWeight(optarg, &script);
6792 process_builtin(findBuiltin(script), weight);
6793 benchmarking_option_set = true;
6794 internal_script_used = true;
6795 break;
6796 case 'c':
6797 benchmarking_option_set = true;
6798 if (!option_parse_int(optarg, "-c/--clients", 1, INT_MAX,
6799 &nclients))
6800 {
6801 exit(1);
6802 }
6803#ifdef HAVE_GETRLIMIT
6804 if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
6805 pg_fatal("getrlimit failed: %m");
6806
6807 if (rlim.rlim_max < nclients + 3)
6808 {
6809 pg_log_error("need at least %d open files, but system limit is %ld",
6810 nclients + 3, (long) rlim.rlim_max);
6811 pg_log_error_hint("Reduce number of clients, or use limit/ulimit to increase the system limit.");
6812 exit(1);
6813 }
6814
6815 if (rlim.rlim_cur < nclients + 3)
6816 {
6817 rlim.rlim_cur = nclients + 3;
6818 if (setrlimit(RLIMIT_NOFILE, &rlim) == -1)
6819 {
6820 pg_log_error("need at least %d open files, but couldn't raise the limit: %m",
6821 nclients + 3);
6822 pg_log_error_hint("Reduce number of clients, or use limit/ulimit to increase the system limit.");
6823 exit(1);
6824 }
6825 }
6826#endif /* HAVE_GETRLIMIT */
6827 break;
6828 case 'C':
6829 benchmarking_option_set = true;
6830 is_connect = true;
6831 break;
6832 case 'd':
6834 break;
6835 case 'D':
6836 {
6837 char *p;
6838
6839 benchmarking_option_set = true;
6840
6841 if ((p = strchr(optarg, '=')) == NULL || p == optarg || *(p + 1) == '\0')
6842 pg_fatal("invalid variable definition: \"%s\"", optarg);
6843
6844 *p++ = '\0';
6845 if (!putVariable(&state[0].variables, "option", optarg, p))
6846 exit(1);
6847 }
6848 break;
6849 case 'f':
6850 weight = parseScriptWeight(optarg, &script);
6851 process_file(script, weight);
6852 benchmarking_option_set = true;
6853 break;
6854 case 'F':
6855 initialization_option_set = true;
6856 if (!option_parse_int(optarg, "-F/--fillfactor", 10, 100,
6857 &fillfactor))
6858 exit(1);
6859 break;
6860 case 'h':
6862 break;
6863 case 'i':
6864 is_init_mode = true;
6865 break;
6866 case 'I':
6867 pg_free(initialize_steps);
6868 initialize_steps = pg_strdup(optarg);
6869 checkInitSteps(initialize_steps);
6870 initialization_option_set = true;
6871 break;
6872 case 'j': /* jobs */
6873 benchmarking_option_set = true;
6874 if (!option_parse_int(optarg, "-j/--jobs", 1, INT_MAX,
6875 &nthreads))
6876 {
6877 exit(1);
6878 }
6879 break;
6880 case 'l':
6881 benchmarking_option_set = true;
6882 use_log = true;
6883 break;
6884 case 'L':
6885 {
6886 double limit_ms = atof(optarg);
6887
6888 if (limit_ms <= 0.0)
6889 pg_fatal("invalid latency limit: \"%s\"", optarg);
6890 benchmarking_option_set = true;
6891 latency_limit = (int64) (limit_ms * 1000);
6892 }
6893 break;
6894 case 'M':
6895 benchmarking_option_set = true;
6897 if (strcmp(optarg, QUERYMODE[querymode]) == 0)
6898 break;
6899 if (querymode >= NUM_QUERYMODE)
6900 pg_fatal("invalid query mode (-M): \"%s\"", optarg);
6901 break;
6902 case 'n':
6903 is_no_vacuum = true;
6904 break;
6905 case 'N':
6906 process_builtin(findBuiltin("simple-update"), 1);
6907 benchmarking_option_set = true;
6908 internal_script_used = true;
6909 break;
6910 case 'p':
6912 break;
6913 case 'P':
6914 benchmarking_option_set = true;
6915 if (!option_parse_int(optarg, "-P/--progress", 1, INT_MAX,
6916 &progress))
6917 exit(1);
6918 break;
6919 case 'q':
6920 initialization_option_set = true;
6921 use_quiet = true;
6922 break;
6923 case 'r':
6924 benchmarking_option_set = true;
6925 report_per_command = true;
6926 break;
6927 case 'R':
6928 {
6929 /* get a double from the beginning of option value */
6930 double throttle_value = atof(optarg);
6931
6932 benchmarking_option_set = true;
6933
6934 if (throttle_value <= 0.0)
6935 pg_fatal("invalid rate limit: \"%s\"", optarg);
6936 /* Invert rate limit into per-transaction delay in usec */
6937 throttle_delay = 1000000.0 / throttle_value;
6938 }
6939 break;
6940 case 's':
6941 scale_given = true;
6942 if (!option_parse_int(optarg, "-s/--scale", 1, INT_MAX,
6943 &scale))
6944 exit(1);
6945 break;
6946 case 'S':
6947 process_builtin(findBuiltin("select-only"), 1);
6948 benchmarking_option_set = true;
6949 internal_script_used = true;
6950 break;
6951 case 't':
6952 benchmarking_option_set = true;
6953 if (!option_parse_int(optarg, "-t/--transactions", 1, INT_MAX,
6954 &nxacts))
6955 exit(1);
6956 break;
6957 case 'T':
6958 benchmarking_option_set = true;
6959 if (!option_parse_int(optarg, "-T/--time", 1, INT_MAX,
6960 &duration))
6961 exit(1);
6962 break;
6963 case 'U':
6965 break;
6966 case 'v':
6967 benchmarking_option_set = true;
6968 do_vacuum_accounts = true;
6969 break;
6970 case 1: /* unlogged-tables */
6971 initialization_option_set = true;
6972 unlogged_tables = true;
6973 break;
6974 case 2: /* tablespace */
6975 initialization_option_set = true;
6977 break;
6978 case 3: /* index-tablespace */
6979 initialization_option_set = true;
6981 break;
6982 case 4: /* sampling-rate */
6983 benchmarking_option_set = true;
6984 sample_rate = atof(optarg);
6985 if (sample_rate <= 0.0 || sample_rate > 1.0)
6986 pg_fatal("invalid sampling rate: \"%s\"", optarg);
6987 break;
6988 case 5: /* aggregate-interval */
6989 benchmarking_option_set = true;
6990 if (!option_parse_int(optarg, "--aggregate-interval", 1, INT_MAX,
6991 &agg_interval))
6992 exit(1);
6993 break;
6994 case 6: /* progress-timestamp */
6995 progress_timestamp = true;
6996 benchmarking_option_set = true;
6997 break;
6998 case 7: /* log-prefix */
6999 benchmarking_option_set = true;
7001 break;
7002 case 8: /* foreign-keys */
7003 initialization_option_set = true;
7004 foreign_keys = true;
7005 break;
7006 case 9: /* random-seed */
7007 benchmarking_option_set = true;
7008 if (!set_random_seed(optarg))
7009 pg_fatal("error while setting random seed from --random-seed option");
7010 break;
7011 case 10: /* list */
7012 {
7013 const BuiltinScript *s = findBuiltin(optarg);
7014
7015 fprintf(stderr, "-- %s: %s\n%s\n", s->name, s->desc, s->script);
7016 exit(0);
7017 }
7018 break;
7019 case 11: /* partitions */
7020 initialization_option_set = true;
7021 if (!option_parse_int(optarg, "--partitions", 0, INT_MAX,
7022 &partitions))
7023 exit(1);
7024 break;
7025 case 12: /* partition-method */
7026 initialization_option_set = true;
7027 if (pg_strcasecmp(optarg, "range") == 0)
7029 else if (pg_strcasecmp(optarg, "hash") == 0)
7031 else
7032 pg_fatal("invalid partition method, expecting \"range\" or \"hash\", got: \"%s\"",
7033 optarg);
7034 break;
7035 case 13: /* failures-detailed */
7036 benchmarking_option_set = true;
7037 failures_detailed = true;
7038 break;
7039 case 14: /* max-tries */
7040 {
7041 int32 max_tries_arg = atoi(optarg);
7042
7043 if (max_tries_arg < 0)
7044 pg_fatal("invalid number of maximum tries: \"%s\"", optarg);
7045
7046 benchmarking_option_set = true;
7047 max_tries = (uint32) max_tries_arg;
7048 }
7049 break;
7050 case 15: /* verbose-errors */
7051 benchmarking_option_set = true;
7052 verbose_errors = true;
7053 break;
7054 case 16: /* exit-on-abort */
7055 benchmarking_option_set = true;
7056 exit_on_abort = true;
7057 break;
7058 case 17: /* debug */
7060 break;
7061 default:
7062 /* getopt_long already emitted a complaint */
7063 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
7064 exit(1);
7065 }
7066 }
7067
7068 /* set default script if none */
7069 if (num_scripts == 0 && !is_init_mode)
7070 {
7071 process_builtin(findBuiltin("tpcb-like"), 1);
7072 benchmarking_option_set = true;
7073 internal_script_used = true;
7074 }
7075
7076 /* complete SQL command initialization and compute total weight */
7077 for (i = 0; i < num_scripts; i++)
7078 {
7079 Command **commands = sql_script[i].commands;
7080
7081 for (int j = 0; commands[j] != NULL; j++)
7082 if (commands[j]->type == SQL_COMMAND)
7083 postprocess_sql_command(commands[j]);
7084
7085 /* cannot overflow: weight is 32b, total_weight 64b */
7087 }
7088
7089 if (total_weight == 0 && !is_init_mode)
7090 pg_fatal("total script weight must not be zero");
7091
7092 /* show per script stats if several scripts are used */
7093 if (num_scripts > 1)
7094 per_script_stats = true;
7095
7096 /*
7097 * Don't need more threads than there are clients. (This is not merely an
7098 * optimization; throttle_delay is calculated incorrectly below if some
7099 * threads have no clients assigned to them.)
7100 */
7101 if (nthreads > nclients)
7103
7104 /*
7105 * Convert throttle_delay to a per-thread delay time. Note that this
7106 * might be a fractional number of usec, but that's OK, since it's just
7107 * the center of a Poisson distribution of delays.
7108 */
7110
7111 if (dbName == NULL)
7112 {
7113 if (argc > optind)
7114 dbName = argv[optind++];
7115 else
7116 {
7117 if ((env = getenv("PGDATABASE")) != NULL && *env != '\0')
7118 dbName = env;
7119 else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
7120 dbName = env;
7121 else
7123 }
7124 }
7125
7126 if (optind < argc)
7127 {
7128 pg_log_error("too many command-line arguments (first is \"%s\")",
7129 argv[optind]);
7130 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
7131 exit(1);
7132 }
7133
7134 if (is_init_mode)
7135 {
7136 if (benchmarking_option_set)
7137 pg_fatal("some of the specified options cannot be used in initialization (-i) mode");
7138
7139 if (partitions == 0 && partition_method != PART_NONE)
7140 pg_fatal("--partition-method requires greater than zero --partitions");
7141
7142 /* set default method */
7145
7146 if (initialize_steps == NULL)
7147 initialize_steps = pg_strdup(DEFAULT_INIT_STEPS);
7148
7149 if (is_no_vacuum)
7150 {
7151 /* Remove any vacuum step in initialize_steps */
7152 char *p;
7153
7154 while ((p = strchr(initialize_steps, 'v')) != NULL)
7155 *p = ' ';
7156 }
7157
7158 if (foreign_keys)
7159 {
7160 /* Add 'f' to end of initialize_steps, if not already there */
7161 if (strchr(initialize_steps, 'f') == NULL)
7162 {
7163 initialize_steps = (char *)
7164 pg_realloc(initialize_steps,
7165 strlen(initialize_steps) + 2);
7166 strcat(initialize_steps, "f");
7167 }
7168 }
7169
7170 runInitSteps(initialize_steps);
7171 exit(0);
7172 }
7173 else
7174 {
7175 if (initialization_option_set)
7176 pg_fatal("some of the specified options cannot be used in benchmarking mode");
7177 }
7178
7179 if (nxacts > 0 && duration > 0)
7180 pg_fatal("specify either a number of transactions (-t) or a duration (-T), not both");
7181
7182 /* Use DEFAULT_NXACTS if neither nxacts nor duration is specified. */
7183 if (nxacts <= 0 && duration <= 0)
7185
7186 /* --sampling-rate may be used only with -l */
7187 if (sample_rate > 0.0 && !use_log)
7188 pg_fatal("log sampling (--sampling-rate) is allowed only when logging transactions (-l)");
7189
7190 /* --sampling-rate may not be used with --aggregate-interval */
7191 if (sample_rate > 0.0 && agg_interval > 0)
7192 pg_fatal("log sampling (--sampling-rate) and aggregation (--aggregate-interval) cannot be used at the same time");
7193
7194 if (agg_interval > 0 && !use_log)
7195 pg_fatal("log aggregation is allowed only when actually logging transactions");
7196
7197 if (!use_log && logfile_prefix)
7198 pg_fatal("log file prefix (--log-prefix) is allowed only when logging transactions (-l)");
7199
7200 if (duration > 0 && agg_interval > duration)
7201 pg_fatal("number of seconds for aggregation (%d) must not be higher than test duration (%d)", agg_interval, duration);
7202
7203 if (duration > 0 && agg_interval > 0 && duration % agg_interval != 0)
7204 pg_fatal("duration (%d) must be a multiple of aggregation interval (%d)", duration, agg_interval);
7205
7206 if (progress_timestamp && progress == 0)
7207 pg_fatal("--progress-timestamp is allowed only under --progress");
7208
7209 if (!max_tries)
7210 {
7211 if (!latency_limit && duration <= 0)
7212 pg_fatal("an unlimited number of transaction tries can only be used with --latency-limit or a duration (-T)");
7213 }
7214
7215 /*
7216 * save main process id in the global variable because process id will be
7217 * changed after fork.
7218 */
7219 main_pid = (int) getpid();
7220
7221 if (nclients > 1)
7222 {
7223 state = (CState *) pg_realloc(state, sizeof(CState) * nclients);
7224 memset(state + 1, 0, sizeof(CState) * (nclients - 1));
7225
7226 /* copy any -D switch values to all clients */
7227 for (i = 1; i < nclients; i++)
7228 {
7229 int j;
7230
7231 state[i].id = i;
7232 for (j = 0; j < state[0].variables.nvars; j++)
7233 {
7234 Variable *var = &state[0].variables.vars[j];
7235
7236 if (var->value.type != PGBT_NO_VALUE)
7237 {
7238 if (!putVariableValue(&state[i].variables, "startup",
7239 var->name, &var->value))
7240 exit(1);
7241 }
7242 else
7243 {
7244 if (!putVariable(&state[i].variables, "startup",
7245 var->name, var->svalue))
7246 exit(1);
7247 }
7248 }
7249 }
7250 }
7251
7252 /* other CState initializations */
7253 for (i = 0; i < nclients; i++)
7254 {
7255 state[i].cstack = conditional_stack_create();
7256 initRandomState(&state[i].cs_func_rs);
7257 }
7258
7259 /* opening connection... */
7260 con = doConnect();
7261 if (con == NULL)
7262 pg_fatal("could not create connection for setup");
7263
7264 /* report pgbench and server versions */
7265 printVersion(con);
7266
7267 pg_log_debug("pghost: %s pgport: %s nclients: %d %s: %d dbName: %s",
7268 PQhost(con), PQport(con), nclients,
7269 duration <= 0 ? "nxacts" : "duration",
7270 duration <= 0 ? nxacts : duration, PQdb(con));
7271
7272 if (internal_script_used)
7273 GetTableInfo(con, scale_given);
7274
7275 /*
7276 * :scale variables normally get -s or database scale, but don't override
7277 * an explicit -D switch
7278 */
7279 if (lookupVariable(&state[0].variables, "scale") == NULL)
7280 {
7281 for (i = 0; i < nclients; i++)
7282 {
7283 if (!putVariableInt(&state[i].variables, "startup", "scale", scale))
7284 exit(1);
7285 }
7286 }
7287
7288 /*
7289 * Define a :client_id variable that is unique per connection. But don't
7290 * override an explicit -D switch.
7291 */
7292 if (lookupVariable(&state[0].variables, "client_id") == NULL)
7293 {
7294 for (i = 0; i < nclients; i++)
7295 if (!putVariableInt(&state[i].variables, "startup", "client_id", i))
7296 exit(1);
7297 }
7298
7299 /* set default seed for hash functions */
7300 if (lookupVariable(&state[0].variables, "default_seed") == NULL)
7301 {
7303
7304 for (i = 0; i < nclients; i++)
7305 if (!putVariableInt(&state[i].variables, "startup", "default_seed",
7306 (int64) seed))
7307 exit(1);
7308 }
7309
7310 /* set random seed unless overwritten */
7311 if (lookupVariable(&state[0].variables, "random_seed") == NULL)
7312 {
7313 for (i = 0; i < nclients; i++)
7314 if (!putVariableInt(&state[i].variables, "startup", "random_seed",
7315 random_seed))
7316 exit(1);
7317 }
7318
7319 if (!is_no_vacuum)
7320 {
7321 fprintf(stderr, "starting vacuum...");
7322 tryExecuteStatement(con, "vacuum pgbench_branches");
7323 tryExecuteStatement(con, "vacuum pgbench_tellers");
7324 tryExecuteStatement(con, "truncate pgbench_history");
7325 fprintf(stderr, "end.\n");
7326
7327 if (do_vacuum_accounts)
7328 {
7329 fprintf(stderr, "starting vacuum pgbench_accounts...");
7330 tryExecuteStatement(con, "vacuum analyze pgbench_accounts");
7331 fprintf(stderr, "end.\n");
7332 }
7333 }
7334 PQfinish(con);
7335
7336 /* set up thread data structures */
7337 threads = (TState *) pg_malloc(sizeof(TState) * nthreads);
7338 nclients_dealt = 0;
7339
7340 for (i = 0; i < nthreads; i++)
7341 {
7342 TState *thread = &threads[i];
7343
7344 thread->tid = i;
7345 thread->state = &state[nclients_dealt];
7346 thread->nstate =
7347 (nclients - nclients_dealt + nthreads - i - 1) / (nthreads - i);
7348 initRandomState(&thread->ts_choose_rs);
7350 initRandomState(&thread->ts_sample_rs);
7351 thread->logfile = NULL; /* filled in later */
7352 thread->latency_late = 0;
7353 initStats(&thread->stats, 0);
7354
7355 nclients_dealt += thread->nstate;
7356 }
7357
7358 /* all clients must be assigned to a thread */
7359 Assert(nclients_dealt == nclients);
7360
7361 /* get start up time for the whole computation */
7363
7364 /* set alarm if duration is specified. */
7365 if (duration > 0)
7367
7369 if (errno != 0)
7370 pg_fatal("could not initialize barrier: %m");
7371
7372 /* start all threads but thread 0 which is executed directly later */
7373 for (i = 1; i < nthreads; i++)
7374 {
7375 TState *thread = &threads[i];
7376
7377 thread->create_time = pg_time_now();
7378 errno = THREAD_CREATE(&thread->thread, threadRun, thread);
7379
7380 if (errno != 0)
7381 pg_fatal("could not create thread: %m");
7382 }
7383
7384 /* compute when to stop */
7385 threads[0].create_time = pg_time_now();
7386 if (duration > 0)
7387 end_time = threads[0].create_time + (int64) 1000000 * duration;
7388
7389 /* run thread 0 directly */
7390 (void) threadRun(&threads[0]);
7391
7392 /* wait for other threads and accumulate results */
7393 initStats(&stats, 0);
7394 conn_total_duration = 0;
7395
7396 for (i = 0; i < nthreads; i++)
7397 {
7398 TState *thread = &threads[i];
7399
7400 if (i > 0)
7401 THREAD_JOIN(thread->thread);
7402
7403 for (int j = 0; j < thread->nstate; j++)
7404 if (thread->state[j].state != CSTATE_FINISHED)
7405 exit_code = 2;
7406
7407 /* aggregate thread level stats */
7408 mergeSimpleStats(&stats.latency, &thread->stats.latency);
7409 mergeSimpleStats(&stats.lag, &thread->stats.lag);
7410 stats.cnt += thread->stats.cnt;
7411 stats.skipped += thread->stats.skipped;
7412 stats.retries += thread->stats.retries;
7413 stats.retried += thread->stats.retried;
7415 stats.deadlock_failures += thread->stats.deadlock_failures;
7416 latency_late += thread->latency_late;
7417 conn_total_duration += thread->conn_duration;
7418
7419 /* first recorded benchmarking start time */
7420 if (bench_start == 0 || thread->bench_start < bench_start)
7421 bench_start = thread->bench_start;
7422 }
7423
7424 /*
7425 * All connections should be already closed in threadRun(), so this
7426 * disconnect_all() will be a no-op, but clean up the connections just to
7427 * be sure. We don't need to measure the disconnection delays here.
7428 */
7430
7431 /*
7432 * Beware that performance of short benchmarks with many threads and
7433 * possibly long transactions can be deceptive because threads do not
7434 * start and finish at the exact same time. The total duration computed
7435 * here encompasses all transactions so that tps shown is somehow slightly
7436 * underestimated.
7437 */
7438 printResults(&stats, pg_time_now() - bench_start, conn_total_duration,
7439 bench_start - start_time, latency_late);
7440
7442
7443 if (exit_code != 0)
7444 pg_log_error("Run was aborted; the above results are incomplete.");
7445
7446 return exit_code;
7447}
7448
7450threadRun(void *arg)
7451{
7452 TState *thread = (TState *) arg;
7453 CState *state = thread->state;
7455 int nstate = thread->nstate;
7456 int remains = nstate; /* number of remaining clients */
7457 socket_set *sockets = alloc_socket_set(nstate);
7458 int64 thread_start,
7459 last_report,
7460 next_report;
7461 StatsData last,
7462 aggs;
7463
7464 /* open log file if requested */
7465 if (use_log)
7466 {
7467 char logpath[MAXPGPATH];
7468 char *prefix = logfile_prefix ? logfile_prefix : "pgbench_log";
7469
7470 if (thread->tid == 0)
7471 snprintf(logpath, sizeof(logpath), "%s.%d", prefix, main_pid);
7472 else
7473 snprintf(logpath, sizeof(logpath), "%s.%d.%d", prefix, main_pid, thread->tid);
7474
7475 thread->logfile = fopen(logpath, "w");
7476
7477 if (thread->logfile == NULL)
7478 pg_fatal("could not open logfile \"%s\": %m", logpath);
7479 }
7480
7481 /* explicitly initialize the state machines */
7482 for (int i = 0; i < nstate; i++)
7484
7485 /* READY */
7487
7488 thread_start = pg_time_now();
7489 thread->started_time = thread_start;
7490 thread->conn_duration = 0;
7491 last_report = thread_start;
7492 next_report = last_report + (int64) 1000000 * progress;
7493
7494 /* STEADY */
7495 if (!is_connect)
7496 {
7497 /* make connections to the database before starting */
7498 for (int i = 0; i < nstate; i++)
7499 {
7500 if ((state[i].con = doConnect()) == NULL)
7501 {
7502 /* coldly abort on initial connection failure */
7503 pg_fatal("could not create connection for client %d",
7504 state[i].id);
7505 }
7506 }
7507 }
7508
7509 /* GO */
7511
7512 start = pg_time_now();
7513 thread->bench_start = start;
7514 thread->throttle_trigger = start;
7515
7516 /*
7517 * The log format currently has Unix epoch timestamps with whole numbers
7518 * of seconds. Round the first aggregate's start time down to the nearest
7519 * Unix epoch second (the very first aggregate might really have started a
7520 * fraction of a second later, but later aggregates are measured from the
7521 * whole number time that is actually logged).
7522 */
7523 initStats(&aggs, (start + epoch_shift) / 1000000 * 1000000);
7524 last = aggs;
7525
7526 /* loop till all clients have terminated */
7527 while (remains > 0)
7528 {
7529 int nsocks; /* number of sockets to be waited for */
7530 pg_time_usec_t min_usec;
7531 pg_time_usec_t now = 0; /* set this only if needed */
7532
7533 /*
7534 * identify which client sockets should be checked for input, and
7535 * compute the nearest time (if any) at which we need to wake up.
7536 */
7537 clear_socket_set(sockets);
7538 nsocks = 0;
7539 min_usec = PG_INT64_MAX;
7540 for (int i = 0; i < nstate; i++)
7541 {
7542 CState *st = &state[i];
7543
7544 if (st->state == CSTATE_SLEEP || st->state == CSTATE_THROTTLE)
7545 {
7546 /* a nap from the script, or under throttling */
7547 pg_time_usec_t this_usec;
7548
7549 /* get current time if needed */
7551
7552 /* min_usec should be the minimum delay across all clients */
7553 this_usec = (st->state == CSTATE_SLEEP ?
7554 st->sleep_until : st->txn_scheduled) - now;
7555 if (min_usec > this_usec)
7556 min_usec = this_usec;
7557 }
7558 else if (st->state == CSTATE_WAIT_RESULT ||
7560 {
7561 /*
7562 * waiting for result from server - nothing to do unless the
7563 * socket is readable
7564 */
7565 int sock = PQsocket(st->con);
7566
7567 if (sock < 0)
7568 {
7569 pg_log_error("invalid socket: %s", PQerrorMessage(st->con));
7570 goto done;
7571 }
7572
7573 add_socket_to_set(sockets, sock, nsocks++);
7574 }
7575 else if (st->state != CSTATE_ABORTED &&
7576 st->state != CSTATE_FINISHED)
7577 {
7578 /*
7579 * This client thread is ready to do something, so we don't
7580 * want to wait. No need to examine additional clients.
7581 */
7582 min_usec = 0;
7583 break;
7584 }
7585 }
7586
7587 /* also wake up to print the next progress report on time */
7588 if (progress && min_usec > 0 && thread->tid == 0)
7589 {
7591
7592 if (now >= next_report)
7593 min_usec = 0;
7594 else if ((next_report - now) < min_usec)
7595 min_usec = next_report - now;
7596 }
7597
7598 /*
7599 * If no clients are ready to execute actions, sleep until we receive
7600 * data on some client socket or the timeout (if any) elapses.
7601 */
7602 if (min_usec > 0)
7603 {
7604 int rc = 0;
7605
7606 if (min_usec != PG_INT64_MAX)
7607 {
7608 if (nsocks > 0)
7609 {
7610 rc = wait_on_socket_set(sockets, min_usec);
7611 }
7612 else /* nothing active, simple sleep */
7613 {
7614 pg_usleep(min_usec);
7615 }
7616 }
7617 else /* no explicit delay, wait without timeout */
7618 {
7619 rc = wait_on_socket_set(sockets, 0);
7620 }
7621
7622 if (rc < 0)
7623 {
7624 if (errno == EINTR)
7625 {
7626 /* On EINTR, go back to top of loop */
7627 continue;
7628 }
7629 /* must be something wrong */
7630 pg_log_error("%s() failed: %m", SOCKET_WAIT_METHOD);
7631 goto done;
7632 }
7633 }
7634 else
7635 {
7636 /* min_usec <= 0, i.e. something needs to be executed now */
7637
7638 /* If we didn't wait, don't try to read any data */
7639 clear_socket_set(sockets);
7640 }
7641
7642 /* ok, advance the state machine of each connection */
7643 nsocks = 0;
7644 for (int i = 0; i < nstate; i++)
7645 {
7646 CState *st = &state[i];
7647
7648 if (st->state == CSTATE_WAIT_RESULT ||
7650 {
7651 /* don't call advanceConnectionState unless data is available */
7652 int sock = PQsocket(st->con);
7653
7654 if (sock < 0)
7655 {
7656 pg_log_error("invalid socket: %s", PQerrorMessage(st->con));
7657 goto done;
7658 }
7659
7660 if (!socket_has_input(sockets, sock, nsocks++))
7661 continue;
7662 }
7663 else if (st->state == CSTATE_FINISHED ||
7664 st->state == CSTATE_ABORTED)
7665 {
7666 /* this client is done, no need to consider it anymore */
7667 continue;
7668 }
7669
7670 advanceConnectionState(thread, st, &aggs);
7671
7672 /*
7673 * If --exit-on-abort is used, the program is going to exit when
7674 * any client is aborted.
7675 */
7676 if (exit_on_abort && st->state == CSTATE_ABORTED)
7677 goto done;
7678
7679 /*
7680 * If advanceConnectionState changed client to finished state,
7681 * that's one fewer client that remains.
7682 */
7683 else if (st->state == CSTATE_FINISHED ||
7684 st->state == CSTATE_ABORTED)
7685 remains--;
7686 }
7687
7688 /* progress report is made by thread 0 for all threads */
7689 if (progress && thread->tid == 0)
7690 {
7691 pg_time_usec_t now2 = pg_time_now();
7692
7693 if (now2 >= next_report)
7694 {
7695 /*
7696 * Horrible hack: this relies on the thread pointer we are
7697 * passed to be equivalent to threads[0], that is the first
7698 * entry of the threads array. That is why this MUST be done
7699 * by thread 0 and not any other.
7700 */
7701 printProgressReport(thread, thread_start, now2,
7702 &last, &last_report);
7703
7704 /*
7705 * Ensure that the next report is in the future, in case
7706 * pgbench/postgres got stuck somewhere.
7707 */
7708 do
7709 {
7710 next_report += (int64) 1000000 * progress;
7711 } while (now2 >= next_report);
7712 }
7713 }
7714 }
7715
7716done:
7717 if (exit_on_abort)
7718 {
7719 /*
7720 * Abort if any client is not finished, meaning some error occurred.
7721 */
7722 for (int i = 0; i < nstate; i++)
7723 {
7724 if (state[i].state != CSTATE_FINISHED)
7725 {
7726 pg_log_error("Run was aborted due to an error in thread %d",
7727 thread->tid);
7728 exit(2);
7729 }
7730 }
7731 }
7732
7733 disconnect_all(state, nstate);
7734
7735 if (thread->logfile)
7736 {
7737 if (agg_interval > 0)
7738 {
7739 /* log aggregated but not yet reported transactions */
7740 doLog(thread, state, &aggs, false, 0, 0);
7741 }
7742 fclose(thread->logfile);
7743 thread->logfile = NULL;
7744 }
7745 free_socket_set(sockets);
7747}
7748
7749static void
7750finishCon(CState *st)
7751{
7752 if (st->con != NULL)
7753 {
7754 PQfinish(st->con);
7755 st->con = NULL;
7756 }
7757}
7758
7759/*
7760 * Support for duration option: set timer_exceeded after so many seconds.
7761 */
7762
7763#ifndef WIN32
7764
7765static void
7767{
7768 timer_exceeded = true;
7769}
7770
7771static void
7772setalarm(int seconds)
7773{
7775 alarm(seconds);
7776}
7777
7778#else /* WIN32 */
7779
7780static VOID CALLBACK
7781win32_timer_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
7782{
7783 timer_exceeded = true;
7784}
7785
7786static void
7787setalarm(int seconds)
7788{
7789 HANDLE queue;
7790 HANDLE timer;
7791
7792 /* This function will be called at most once, so we can cheat a bit. */
7793 queue = CreateTimerQueue();
7794 if (seconds > ((DWORD) -1) / 1000 ||
7795 !CreateTimerQueueTimer(&timer, queue,
7796 win32_timer_callback, NULL, seconds * 1000, 0,
7797 WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE))
7798 pg_fatal("failed to set timer");
7799}
7800
7801#endif /* WIN32 */
7802
7803
7804/*
7805 * These functions provide an abstraction layer that hides the syscall
7806 * we use to wait for input on a set of sockets.
7807 *
7808 * Currently there are two implementations, based on ppoll(2) and select(2).
7809 * ppoll() is preferred where available due to its typically higher ceiling
7810 * on the number of usable sockets. We do not use the more-widely-available
7811 * poll(2) because it only offers millisecond timeout resolution, which could
7812 * be problematic with high --rate settings.
7813 *
7814 * Function APIs:
7815 *
7816 * alloc_socket_set: allocate an empty socket set with room for up to
7817 * "count" sockets.
7818 *
7819 * free_socket_set: deallocate a socket set.
7820 *
7821 * clear_socket_set: reset a socket set to empty.
7822 *
7823 * add_socket_to_set: add socket with indicated FD to slot "idx" in the
7824 * socket set. Slots must be filled in order, starting with 0.
7825 *
7826 * wait_on_socket_set: wait for input on any socket in set, or for timeout
7827 * to expire. timeout is measured in microseconds; 0 means wait forever.
7828 * Returns result code of underlying syscall (>=0 if OK, else see errno).
7829 *
7830 * socket_has_input: after waiting, call this to see if given socket has
7831 * input. fd and idx parameters should match some previous call to
7832 * add_socket_to_set.
7833 *
7834 * Note that wait_on_socket_set destructively modifies the state of the
7835 * socket set. After checking for input, caller must apply clear_socket_set
7836 * and add_socket_to_set again before waiting again.
7837 */
7838
7839#ifdef POLL_USING_PPOLL
7840
7841static socket_set *
7842alloc_socket_set(int count)
7843{
7844 socket_set *sa;
7845
7846 sa = (socket_set *) pg_malloc0(offsetof(socket_set, pollfds) +
7847 sizeof(struct pollfd) * count);
7848 sa->maxfds = count;
7849 sa->curfds = 0;
7850 return sa;
7851}
7852
7853static void
7855{
7856 pg_free(sa);
7857}
7858
7859static void
7861{
7862 sa->curfds = 0;
7863}
7864
7865static void
7867{
7868 Assert(idx < sa->maxfds && idx == sa->curfds);
7869 sa->pollfds[idx].fd = fd;
7870 sa->pollfds[idx].events = POLLIN;
7871 sa->pollfds[idx].revents = 0;
7872 sa->curfds++;
7873}
7874
7875static int
7877{
7878 if (usecs > 0)
7879 {
7880 struct timespec timeout;
7881
7882 timeout.tv_sec = usecs / 1000000;
7883 timeout.tv_nsec = (usecs % 1000000) * 1000;
7884 return ppoll(sa->pollfds, sa->curfds, &timeout, NULL);
7885 }
7886 else
7887 {
7888 return ppoll(sa->pollfds, sa->curfds, NULL, NULL);
7889 }
7890}
7891
7892static bool
7894{
7895 /*
7896 * In some cases, threadRun will apply clear_socket_set and then try to
7897 * apply socket_has_input anyway with arguments that it used before that,
7898 * or might've used before that except that it exited its setup loop
7899 * early. Hence, if the socket set is empty, silently return false
7900 * regardless of the parameters. If it's not empty, we can Assert that
7901 * the parameters match a previous call.
7902 */
7903 if (sa->curfds == 0)
7904 return false;
7905
7906 Assert(idx < sa->curfds && sa->pollfds[idx].fd == fd);
7907 return (sa->pollfds[idx].revents & POLLIN) != 0;
7908}
7909
7910#endif /* POLL_USING_PPOLL */
7911
7912#ifdef POLL_USING_SELECT
7913
7915alloc_socket_set(int count)
7916{
7917 return (socket_set *) pg_malloc0(sizeof(socket_set));
7918}
7919
7920static void
7922{
7923 pg_free(sa);
7924}
7925
7926static void
7928{
7929 FD_ZERO(&sa->fds);
7930 sa->maxfd = -1;
7931}
7932
7933static void
7935{
7936 /* See connect_slot() for background on this code. */
7937#ifdef WIN32
7938 if (sa->fds.fd_count + 1 >= FD_SETSIZE)
7939 {
7940 pg_log_error("too many concurrent database clients for this platform: %d",
7941 sa->fds.fd_count + 1);
7942 exit(1);
7943 }
7944#else
7945 if (fd < 0 || fd >= FD_SETSIZE)
7946 {
7947 pg_log_error("socket file descriptor out of range for select(): %d",
7948 fd);
7949 pg_log_error_hint("Try fewer concurrent database clients.");
7950 exit(1);
7951 }
7952#endif
7953 FD_SET(fd, &sa->fds);
7954 if (fd > sa->maxfd)
7955 sa->maxfd = fd;
7956}
7957
7958static int
7960{
7961 if (usecs > 0)
7962 {
7963 struct timeval timeout;
7964
7965 timeout.tv_sec = usecs / 1000000;
7966 timeout.tv_usec = usecs % 1000000;
7967 return select(sa->maxfd + 1, &sa->fds, NULL, NULL, &timeout);
7968 }
7969 else
7970 {
7971 return select(sa->maxfd + 1, &sa->fds, NULL, NULL, NULL);
7972 }
7973}
7974
7975static bool
7977{
7978 return (FD_ISSET(fd, &sa->fds) != 0);
7979}
7980
7981#endif /* POLL_USING_SELECT */
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:262
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1609
static int32 next
Definition: blutils.c:224
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define INT64CONST(x)
Definition: c.h:516
#define Min(x, y)
Definition: c.h:975
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1126
#define Max(x, y)
Definition: c.h:969
#define INT64_FORMAT
Definition: c.h:520
#define SIGNAL_ARGS
Definition: c.h:1320
int64_t int64
Definition: c.h:499
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:434
int8_t int8
Definition: c.h:496
#define FLOAT8_FITS_IN_INT64(num)
Definition: c.h:1063
#define CppAsString2(x)
Definition: c.h:363
int32_t int32
Definition: c.h:498
#define PG_INT64_MAX
Definition: c.h:563
#define PG_INT64_MIN
Definition: c.h:562
uint64_t uint64
Definition: c.h:503
#define unlikely(x)
Definition: c.h:347
uint32_t uint32
Definition: c.h:502
#define lengthof(array)
Definition: c.h:759
volatile sig_atomic_t CancelRequested
Definition: cancel.c:59
void ResetCancelConn(void)
Definition: cancel.c:107
void SetCancelConn(PGconn *conn)
Definition: cancel.c:77
void setup_cancel_handler(void(*query_cancel_callback)(void))
Definition: cancel.c:183
ifState conditional_stack_peek(ConditionalStack cstack)
Definition: conditional.c:106
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:53
ConditionalStack conditional_stack_create(void)
Definition: conditional.c:18
bool conditional_stack_pop(ConditionalStack cstack)
Definition: conditional.c:69
void conditional_stack_destroy(ConditionalStack cstack)
Definition: conditional.c:43
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:140
void conditional_stack_reset(ConditionalStack cstack)
Definition: conditional.c:30
bool conditional_stack_poke(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:118
bool conditional_stack_empty(ConditionalStack cstack)
Definition: conditional.c:130
@ IFSTATE_FALSE
Definition: conditional.h:34
@ IFSTATE_ELSE_TRUE
Definition: conditional.h:40
@ IFSTATE_IGNORED
Definition: conditional.h:37
@ IFSTATE_TRUE
Definition: conditional.h:32
@ IFSTATE_NONE
Definition: conditional.h:31
@ IFSTATE_ELSE_FALSE
Definition: conditional.h:42
void * yyscan_t
Definition: cubedata.h:67
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
struct cursor * cur
Definition: ecpg.c:29
#define _(x)
Definition: elog.c:91
bool expr_lex_one_word(PsqlScanState state, PQExpBuffer word_buf, int *offset)
Definition: exprscan.l:318
char * expr_scanner_get_substring(PsqlScanState state, int start_offset, bool chomp)
Definition: exprscan.l:425
void expr_scanner_finish(yyscan_t yyscanner)
Definition: exprscan.l:402
yyscan_t expr_scanner_init(PsqlScanState state, const char *source, int lineno, int start_offset, const char *command)
Definition: exprscan.l:370
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:7609
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:7447
char * PQport(const PGconn *conn)
Definition: fe-connect.c:7524
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:7564
char * PQhost(const PGconn *conn)
Definition: fe-connect.c:7488
const char * PQparameterStatus(const PGconn *conn, const char *paramName)
Definition: fe-connect.c:7574
int PQconnectionNeedsPassword(const PGconn *conn)
Definition: fe-connect.c:7672
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:7556
void PQfinish(PGconn *conn)
Definition: fe-connect.c:5290
PGpipelineStatus PQpipelineStatus(const PGconn *conn)
Definition: fe-connect.c:7663
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7619
int PQsocket(const PGconn *conn)
Definition: fe-connect.c:7645
PGconn * PQconnectdbParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:758
int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
Definition: fe-exec.c:1492
void PQfreemem(void *ptr)
Definition: fe-exec.c:4032
PGresult * PQexecParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
Definition: fe-exec.c:2276
int PQexitPipelineMode(PGconn *conn)
Definition: fe-exec.c:3073
int PQenterPipelineMode(PGconn *conn)
Definition: fe-exec.c:3042
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2062
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3411
void PQclear(PGresult *res)
Definition: fe-exec.c:721
int PQendcopy(PGconn *conn)
Definition: fe-exec.c:2949
int PQsendPipelineSync(PGconn *conn)
Definition: fe-exec.c:3282
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
int PQputline(PGconn *conn, const char *string)
Definition: fe-exec.c:2918
PGresult * PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes)
Definition: fe-exec.c:2306
char * PQfname(const PGresult *res, int field_num)
Definition: fe-exec.c:3567
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1984
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3901
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3466
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1416
int PQpipelineSync(PGconn *conn)
Definition: fe-exec.c:3272
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2031
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2262
int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char *const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat)
Definition: fe-exec.c:1633
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
Definition: fe-exec.c:4369
int PQnfields(const PGresult *res)
Definition: fe-exec.c:3489
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
void pg_free(void *ptr)
Definition: fe_memutils.c:105
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:60
#define no_argument
Definition: getopt_long.h:25
#define required_argument
Definition: getopt_long.h:26
Assert(PointerIsAligned(start, uint64))
return str start
const char * str
#define free(a)
Definition: header.h:65
static const FormData_pg_attribute a1
Definition: heap.c:144
static const FormData_pg_attribute a2
Definition: heap.c:157
struct parser_state ps
long val
Definition: informix.c:689
static struct @165 value
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_GET_MICROSEC(t)
Definition: instr_time.h:194
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:293
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:262
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:235
int b
Definition: isn.c:74
int x
Definition: isn.c:75
int j
Definition: isn.c:78
int i
Definition: isn.c:77
static const JsonPathKeyword keywords[]
@ CONNECTION_BAD
Definition: libpq-fe.h:85
@ PGRES_COPY_IN
Definition: libpq-fe.h:132
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:125
@ PGRES_FATAL_ERROR
Definition: libpq-fe.h:136
@ PGRES_EMPTY_QUERY
Definition: libpq-fe.h:124
@ PGRES_PIPELINE_SYNC
Definition: libpq-fe.h:139
@ PGRES_NONFATAL_ERROR
Definition: libpq-fe.h:135
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:128
PGTransactionStatusType
Definition: libpq-fe.h:146
@ PQTRANS_INTRANS
Definition: libpq-fe.h:149
@ PQTRANS_IDLE
Definition: libpq-fe.h:147
@ PQTRANS_ACTIVE
Definition: libpq-fe.h:148
@ PQTRANS_UNKNOWN
Definition: libpq-fe.h:151
@ PQTRANS_INERROR
Definition: libpq-fe.h:150
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:187
@ PQ_PIPELINE_ON
Definition: libpq-fe.h:188
void pg_logging_increase_verbosity(void)
Definition: logging.c:185
void pg_logging_init(const char *argv0)
Definition: logging.c:83
enum pg_log_level __pg_log_level
Definition: logging.c:21
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_error_hint(...)
Definition: logging.h:112
#define pg_log_info(...)
Definition: logging.h:124
@ PG_LOG_DEBUG
Definition: logging.h:26
#define pg_log_error_detail(...)
Definition: logging.h:109
#define pg_log_debug(...)
Definition: logging.h:133
bool option_parse_int(const char *optarg, const char *optname, int min_range, int max_range, int *result)
Definition: option_utils.c:50
void * arg
#define pg_fatal(...)
static int pg_leftmost_one_pos64(uint64 word)
Definition: pg_bitutils.h:72
#define MAXPGPATH
const void size_t len
static time_t start_time
Definition: pg_ctl.c:95
static int server_version
Definition: pg_dumpall.c:113
static char * filename
Definition: pg_dumpall.c:123
PGDLLIMPORT int optind
Definition: getopt.c:51
PGDLLIMPORT char * optarg
Definition: getopt.c:53
static const struct lconv_member_info table[]
double pg_prng_double(pg_prng_state *state)
Definition: pg_prng.c:268
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:144
uint64 pg_prng_uint64(pg_prng_state *state)
Definition: pg_prng.c:134
void pg_prng_seed(pg_prng_state *state, uint64 seed)
Definition: pg_prng.c:89
double pg_prng_double_normal(pg_prng_state *state)
Definition: pg_prng.c:290
static FILE * logfile
Definition: pg_regress.c:126
static rewind_source * source
Definition: pg_rewind.c:89
static char * buf
Definition: pg_test_fsync.c:72
void syntax_error(const char *source, int lineno, const char *line, const char *command, const char *msg, const char *more, int column)
Definition: pgbench.c:5517
static QueryMode querymode
Definition: pgbench.c:714
static char * index_tablespace
Definition: pgbench.c:218
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)
Definition: pgbench.c:6387
MetaCommand
Definition: pgbench.c:689
@ META_ELSE
Definition: pgbench.c:699
@ META_SETSHELL
Definition: pgbench.c:692
@ META_ENDIF
Definition: pgbench.c:700
@ META_SHELL
Definition: pgbench.c:693
@ META_STARTPIPELINE
Definition: pgbench.c:701
@ META_SET
Definition: pgbench.c:691
@ META_ELIF
Definition: pgbench.c:698
@ META_SYNCPIPELINE
Definition: pgbench.c:702
@ META_SLEEP
Definition: pgbench.c:694
@ META_NONE
Definition: pgbench.c:690
@ META_IF
Definition: pgbench.c:697
@ META_ENDPIPELINE
Definition: pgbench.c:703
@ META_ASET
Definition: pgbench.c:696
@ META_GSET
Definition: pgbench.c:695
static bool putVariableInt(Variables *variables, const char *context, char *name, int64 value)
Definition: pgbench.c:1897
static pg_time_usec_t pg_time_now(void)
Definition: pgbench.c:877
bool strtodouble(const char *str, bool errorOK, double *dv)
Definition: pgbench.c:1085
static void accumStats(StatsData *stats, bool skipped, double lat, double lag, EStatus estatus, int64 tries)
Definition: pgbench.c:1477
#define THREAD_FUNC_CC
Definition: pgbench.c:147
#define THREAD_FUNC_RETURN_TYPE
Definition: pgbench.c:145
static void initCreatePKeys(PGconn *con)
Definition: pgbench.c:5178
static uint32 max_tries
Definition: pgbench.c:290
static void GetTableInfo(PGconn *con, bool scale_given)
Definition: pgbench.c:5347
#define MM2_MUL_TIMES_8
Definition: pgbench.c:87
static Command * create_sql_command(PQExpBuffer buf, const char *source)
Definition: pgbench.c:5588
static void printVerboseErrorMessages(CState *st, pg_time_usec_t *now, bool is_retry)
Definition: pgbench.c:3572
static void initRandomState(pg_prng_state *state)
Definition: pgbench.c:1114
static bool isLazyFunc(PgBenchFunction func)
Definition: pgbench.c:2151
static double throttle_delay
Definition: pgbench.c:204
static bool per_script_stats
Definition: pgbench.c:261
static char * skip_sql_comments(char *sql_command)
Definition: pgbench.c:5553
static int64 getZipfianRand(pg_prng_state *state, int64 min, int64 max, double s)
Definition: pgbench.c:1257
#define THREAD_BARRIER_WAIT(barrier)
Definition: pgbench.c:155
#define MM2_ROT
Definition: pgbench.c:88
static char * read_file_contents(FILE *fd)
Definition: pgbench.c:6076
static void setIntValue(PgBenchValue *pv, int64 ival)
Definition: pgbench.c:2136
static int64 latency_limit
Definition: pgbench.c:212
QueryMode
Definition: pgbench.c:707
@ QUERY_PREPARED
Definition: pgbench.c:710
@ NUM_QUERYMODE
Definition: pgbench.c:711
@ QUERY_SIMPLE
Definition: pgbench.c:708
@ QUERY_EXTENDED
Definition: pgbench.c:709
static bool use_log
Definition: pgbench.c:257
static THREAD_FUNC_RETURN_TYPE THREAD_FUNC_CC threadRun(void *arg)
Definition: pgbench.c:7449
#define MAX_ARGS
Definition: pgbench.c:686
#define SHELL_COMMAND_SIZE
Definition: pgbench.c:349
static void setalarm(int seconds)
Definition: pgbench.c:7771
static int nthreads
Definition: pgbench.c:265
struct BuiltinScript BuiltinScript
static void initTeller(PQExpBufferData *sql, int64 curr)
Definition: pgbench.c:4945
static TStatus getTransactionStatus(PGconn *con)
Definition: pgbench.c:3535
static int64 end_time
Definition: pgbench.c:176
static bool exit_on_abort
Definition: pgbench.c:771
static bool coerceToInt(PgBenchValue *pval, int64 *ival)
Definition: pgbench.c:2071
static void setNullValue(PgBenchValue *pv)
Definition: pgbench.c:2120
#define SOCKET_WAIT_METHOD
Definition: pgbench.c:107
static bool doRetry(CState *st, pg_time_usec_t *now)
Definition: pgbench.c:3449
static bool evalLazyFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2158
#define ERRCODE_T_R_DEADLOCK_DETECTED
Definition: pgbench.c:78
static int64 getExponentialRand(pg_prng_state *state, int64 min, int64 max, double parameter)
Definition: pgbench.c:1139
static void free_socket_set(socket_set *sa)
Definition: pgbench.c:7920
static void CheckConditional(const ParsedScript *ps)
Definition: pgbench.c:5885
static bool sendCommand(CState *st, Command *command)
Definition: pgbench.c:3176
static void doLog(TState *thread, CState *st, StatsData *agg, bool skipped, double latency, double lag)
Definition: pgbench.c:4569
#define COMMANDS_ALLOC_NUM
#define ERRCODE_T_R_SERIALIZATION_FAILURE
Definition: pgbench.c:77
static void prepareCommandsInPipeline(CState *st)
Definition: pgbench.c:3143
int main(int argc, char **argv)
Definition: pgbench.c:6658
TStatus
Definition: pgbench.c:470
@ TSTATUS_CONN_ERROR
Definition: pgbench.c:473
@ TSTATUS_IDLE
Definition: pgbench.c:471
@ TSTATUS_IN_BLOCK
Definition: pgbench.c:472
@ TSTATUS_OTHER_ERROR
Definition: pgbench.c:474
static int agg_interval
Definition: pgbench.c:259
static bool putVariable(Variables *variables, const char *context, char *name, const char *value)
Definition: pgbench.c:1855
static int nclients
Definition: pgbench.c:264
static int scale
Definition: pgbench.c:182
static void finishCon(CState *st)
Definition: pgbench.c:7749
static int compareVariableNames(const void *v1, const void *v2)
Definition: pgbench.c:1622
#define MAX_SCRIPTS
Definition: pgbench.c:348
static void printVersion(PGconn *con)
Definition: pgbench.c:6356
static void initBranch(PQExpBufferData *sql, int64 curr)
Definition: pgbench.c:4936
#define WSEP
Definition: pgbench.c:302
struct socket_set socket_set
static bool evaluateExpr(CState *st, PgBenchExpr *expr, PgBenchValue *retval)
Definition: pgbench.c:2858
static bool parseQuery(Command *cmd)
Definition: pgbench.c:5456
#define DEFAULT_NXACTS
Definition: pgbench.c:167
static void initStats(StatsData *sd, pg_time_usec_t start)
Definition: pgbench.c:1460
static pg_prng_state base_random_sequence
Definition: pgbench.c:478
static void setDoubleValue(PgBenchValue *pv, double dval)
Definition: pgbench.c:2144
static void checkInitSteps(const char *initialize_steps)
Definition: pgbench.c:5242
static int progress
Definition: pgbench.c:262
static void createPartitions(PGconn *con)
Definition: pgbench.c:4762
static char * parseVariable(const char *sql, int *eaten)
Definition: pgbench.c:1915
static void initDropTables(PGconn *con)
Definition: pgbench.c:4740
static char * getVariable(Variables *variables, char *name)
Definition: pgbench.c:1657
int64 pg_time_usec_t
Definition: pgbench.c:371
static bool is_connect
Definition: pgbench.c:266
static void clear_socket_set(socket_set *sa)
Definition: pgbench.c:7926
static void free_command(Command *command)
Definition: pgbench.c:5617
static void postprocess_sql_command(Command *my_command)
Definition: pgbench.c:5637
static bool progress_timestamp
Definition: pgbench.c:263
static const char *const QUERYMODE[]
Definition: pgbench.c:715
ConnectionStateEnum
Definition: pgbench.c:487
@ CSTATE_START_TX
Definition: pgbench.c:506
@ CSTATE_END_TX
Definition: pgbench.c:584
@ CSTATE_RETRY
Definition: pgbench.c:573
@ CSTATE_FINISHED
Definition: pgbench.c:591
@ CSTATE_SKIP_COMMAND
Definition: pgbench.c:546
@ CSTATE_THROTTLE
Definition: pgbench.c:516
@ CSTATE_FAILURE
Definition: pgbench.c:574
@ CSTATE_START_COMMAND
Definition: pgbench.c:542
@ CSTATE_END_COMMAND
Definition: pgbench.c:545
@ CSTATE_WAIT_RESULT
Definition: pgbench.c:543
@ CSTATE_CHOOSE_SCRIPT
Definition: pgbench.c:494
@ CSTATE_WAIT_ROLLBACK_RESULT
Definition: pgbench.c:572
@ CSTATE_ABORTED
Definition: pgbench.c:590
@ CSTATE_PREPARE_THROTTLE
Definition: pgbench.c:515
@ CSTATE_SLEEP
Definition: pgbench.c:544
@ CSTATE_ERROR
Definition: pgbench.c:571
static int partitions
Definition: pgbench.c:224
#define ntellers
Definition: pgbench.c:245
static int nxacts
Definition: pgbench.c:174
static void handle_sig_alarm(SIGNAL_ARGS)
Definition: pgbench.c:7765
static double sample_rate
Definition: pgbench.c:198
static bool evalFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2842
static bool runShellCommand(Variables *variables, char *variable, char **argv, int argc)
Definition: pgbench.c:2943
#define MIN_ZIPFIAN_PARAM
Definition: pgbench.c:171
static const BuiltinScript * findBuiltin(const char *name)
Definition: pgbench.c:6154
struct Command Command
#define PARAMS_ARRAY_SIZE
void(* initRowMethod)(PQExpBufferData *sql, int64 curr)
Definition: pgbench.c:844
static bool report_per_command
Definition: pgbench.c:267
static char * replaceVariable(char **sql, char *param, int len, char *value)
Definition: pgbench.c:1942
static void initGenerateDataServerSide(PGconn *con)
Definition: pgbench.c:5120
static bool makeVariableValue(Variable *var)
Definition: pgbench.c:1690
static MetaCommand getMetaCommand(const char *cmd)
Definition: pgbench.c:2901
static void mergeSimpleStats(SimpleStats *acc, SimpleStats *ss)
Definition: pgbench.c:1444
#define THREAD_JOIN(handle)
Definition: pgbench.c:150
static void printSimpleStats(const char *prefix, SimpleStats *ss)
Definition: pgbench.c:6342
#define THREAD_T
Definition: pgbench.c:144
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:79
static void listAvailableScripts(void)
Definition: pgbench.c:6142
static char * logfile_prefix
Definition: pgbench.c:299
#define THREAD_BARRIER_T
Definition: pgbench.c:152
#define PG_TIME_GET_DOUBLE(t)
Definition: pgbench.c:893
#define ALL_INIT_STEPS
Definition: pgbench.c:164
static bool set_random_seed(const char *seed)
Definition: pgbench.c:6616
static void add_socket_to_set(socket_set *sa, int fd, int idx)
Definition: pgbench.c:7933
static char get_table_relkind(PGconn *con, const char *table)
Definition: pgbench.c:852
static int discardUntilSync(CState *st)
Definition: pgbench.c:3495
static EStatus getSQLErrorStatus(const char *sqlState)
Definition: pgbench.c:3229
static int64 total_weight
Definition: pgbench.c:767
#define THREAD_FUNC_RETURN
Definition: pgbench.c:146
static ConnectionStateEnum executeMetaCommand(CState *st, pg_time_usec_t *now)
Definition: pgbench.c:4308
#define VARIABLES_ALLOC_MARGIN
Definition: pgbench.c:311
static void initCreateFKeys(PGconn *con)
Definition: pgbench.c:5216
static const BuiltinScript builtin_script[]
Definition: pgbench.c:781
static int fillfactor
Definition: pgbench.c:188
static int64 getFailures(const StatsData *stats)
Definition: pgbench.c:4527
static ParsedScript sql_script[MAX_SCRIPTS]
Definition: pgbench.c:765
static bool canRetryError(EStatus estatus)
Definition: pgbench.c:3246
static void runInitSteps(const char *initialize_steps)
Definition: pgbench.c:5262
static int64 permute(const int64 val, const int64 isize, const int64 seed)
Definition: pgbench.c:1329
static Command * process_backslash_command(PsqlScanState sstate, const char *source, int lineno, int start_offset)
Definition: pgbench.c:5674
static void commandFailed(CState *st, const char *cmd, const char *message)
Definition: pgbench.c:3049
static int chooseScript(TState *thread)
Definition: pgbench.c:3068
static bool evalStandardFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2275
static void addScript(const ParsedScript *script)
Definition: pgbench.c:6227
static void setBoolValue(PgBenchValue *pv, bool bval)
Definition: pgbench.c:2128
static void initTruncateTables(PGconn *con)
Definition: pgbench.c:4926
static Variable * lookupCreateVariable(Variables *variables, const char *context, char *name)
Definition: pgbench.c:1818
bool strtoint64(const char *str, bool errorOK, int64 *result)
Definition: pgbench.c:1014
EStatus
Definition: pgbench.c:456
@ ESTATUS_DEADLOCK_ERROR
Definition: pgbench.c:462
@ ESTATUS_META_COMMAND_ERROR
Definition: pgbench.c:458
@ ESTATUS_OTHER_SQL_ERROR
Definition: pgbench.c:463
@ ESTATUS_NO_ERROR
Definition: pgbench.c:457
@ ESTATUS_SERIALIZATION_ERROR
Definition: pgbench.c:461
struct StatsData StatsData
static int64 computeIterativeZipfian(pg_prng_state *state, int64 n, double s)
Definition: pgbench.c:1227
static void advanceConnectionState(TState *thread, CState *st, StatsData *agg)
Definition: pgbench.c:3610
static void ConditionError(const char *desc, int cmdn, const char *msg)
Definition: pgbench.c:5875
static bool evaluateSleep(Variables *variables, int argc, char **argv, int *usecs)
Definition: pgbench.c:3404
static void process_builtin(const BuiltinScript *bi, int weight)
Definition: pgbench.c:6135
static int parseScriptWeight(const char *option, char **script)
Definition: pgbench.c:6190
struct SimpleStats SimpleStats
struct ParsedScript ParsedScript
#define SQL_COMMAND
Definition: pgbench.c:679
static char * valueTypeName(PgBenchValue *pval)
Definition: pgbench.c:2008
static void initVacuum(PGconn *con)
Definition: pgbench.c:5165
static bool putVariableValue(Variables *variables, const char *context, char *name, const PgBenchValue *value)
Definition: pgbench.c:1878
static void initAccount(PQExpBufferData *sql, int64 curr)
Definition: pgbench.c:4954
static void commandError(CState *st, const char *message)
Definition: pgbench.c:3059
static void tryExecuteStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1542
static bool valid_variable_name(const char *name)
Definition: pgbench.c:1764
static partition_method_t partition_method
Definition: pgbench.c:234
static int64 getrand(pg_prng_state *state, int64 min, int64 max)
Definition: pgbench.c:1128
static const char *const PARTITION_METHOD[]
Definition: pgbench.c:235
#define MAX_FARGS
Definition: pgbench.c:2268
static void getQueryParams(Variables *variables, const Command *command, const char **params)
Definition: pgbench.c:1998
static volatile sig_atomic_t timer_exceeded
Definition: pgbench.c:304
static const char * pghost
Definition: pgbench.c:295
static void enlargeVariables(Variables *variables, int needed)
Definition: pgbench.c:1799
static THREAD_BARRIER_T barrier
Definition: pgbench.c:481
static void printProgressReport(TState *threads, int64 test_start, pg_time_usec_t now, StatsData *last, int64 *last_report)
Definition: pgbench.c:6248
static void processXactStats(TState *thread, CState *st, pg_time_usec_t *now, bool skipped, StatsData *agg)
Definition: pgbench.c:4689
static const char * username
Definition: pgbench.c:297
static bool unlogged_tables
Definition: pgbench.c:193
static void initSimpleStats(SimpleStats *ss)
Definition: pgbench.c:1420
#define LOG_STEP_SECONDS
Definition: pgbench.c:166
static int64 getHashMurmur2(int64 val, uint64 seed)
Definition: pgbench.c:1296
static int duration
Definition: pgbench.c:175
static void process_file(const char *filename, int weight)
Definition: pgbench.c:6109
static int main_pid
Definition: pgbench.c:270
#define nbranches
Definition: pgbench.c:244
partition_method_t
Definition: pgbench.c:228
@ PART_NONE
Definition: pgbench.c:229
@ PART_RANGE
Definition: pgbench.c:230
@ PART_HASH
Definition: pgbench.c:231
static const PsqlScanCallbacks pgbench_callbacks
Definition: pgbench.c:847
static void ParseScript(const char *script, const char *desc, int weight)
Definition: pgbench.c:5935
static char * assignVariables(Variables *variables, char *sql)
Definition: pgbench.c:1962
static void prepareCommand(CState *st, int command_num)
Definition: pgbench.c:3110
#define naccounts
Definition: pgbench.c:246
#define THREAD_BARRIER_INIT(barrier, n)
Definition: pgbench.c:153
#define FNV_OFFSET_BASIS
Definition: pgbench.c:85
#define FNV_PRIME
Definition: pgbench.c:84
static bool socket_has_input(socket_set *sa, int fd, int idx)
Definition: pgbench.c:7975
static PGconn * doConnect(void)
Definition: pgbench.c:1557
static const char * progname
Definition: pgbench.c:300
static bool valueTruth(PgBenchValue *pval)
Definition: pgbench.c:2050
static int num_scripts
Definition: pgbench.c:766
static void usage(void)
Definition: pgbench.c:896
static bool is_an_int(const char *str)
Definition: pgbench.c:977
static void pg_time_now_lazy(pg_time_usec_t *now)
Definition: pgbench.c:887
#define MM2_MUL
Definition: pgbench.c:86
static int64 getGaussianRand(pg_prng_state *state, int64 min, int64 max, double parameter)
Definition: pgbench.c:1163
static void addToSimpleStats(SimpleStats *ss, double val)
Definition: pgbench.c:1429
static const char * pgport
Definition: pgbench.c:296
static void initPopulateTable(PGconn *con, const char *table, int64 base, initRowMethod init_row)
Definition: pgbench.c:4963
static void allocCStatePrepared(CState *st)
Definition: pgbench.c:3090
static void disconnect_all(CState *state, int length)
Definition: pgbench.c:4728
#define DEFAULT_INIT_STEPS
Definition: pgbench.c:163
static void initCreateTables(PGconn *con)
Definition: pgbench.c:4831
static bool verbose_errors
Definition: pgbench.c:769
static int64 random_seed
Definition: pgbench.c:238
#define MIN_GAUSSIAN_PARAM
Definition: pgbench.c:169
#define M_PI
Definition: pgbench.c:74
#define SCALE_32BIT_THRESHOLD
Definition: pgbench.c:255
static const char * dbName
Definition: pgbench.c:298
static int64 getPoissonRand(pg_prng_state *state, double center)
Definition: pgbench.c:1205
static int wait_on_socket_set(socket_set *sa, int64 usecs)
Definition: pgbench.c:7958
static void executeStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1526
#define THREAD_CREATE(handle, function, arg)
Definition: pgbench.c:148
static Variable * lookupVariable(Variables *variables, char *name)
Definition: pgbench.c:1630
static int64 getHashFnv1a(int64 val, uint64 seed)
Definition: pgbench.c:1271
static char * tablespace
Definition: pgbench.c:217
static bool coerceToDouble(PgBenchValue *pval, double *dval)
Definition: pgbench.c:2099
static socket_set * alloc_socket_set(int count)
Definition: pgbench.c:7914
static bool failures_detailed
Definition: pgbench.c:292
static void initGenerateDataClientSide(PGconn *con)
Definition: pgbench.c:5088
#define META_COMMAND
Definition: pgbench.c:680
static bool use_quiet
Definition: pgbench.c:258
static bool readCommandResponse(CState *st, MetaCommand meta, char *varprefix)
Definition: pgbench.c:3262
static pg_time_usec_t epoch_shift
Definition: pgbench.c:450
#define MAX_ZIPFIAN_PARAM
Definition: pgbench.c:172
static bool coerceToBool(PgBenchValue *pval, bool *bval)
Definition: pgbench.c:2030
#define THREAD_BARRIER_DESTROY(barrier)
Definition: pgbench.c:156
static const char * getResultString(bool skipped, EStatus estatus)
Definition: pgbench.c:4538
@ ENODE_VARIABLE
Definition: pgbench.h:60
@ ENODE_CONSTANT
Definition: pgbench.h:59
@ ENODE_FUNCTION
Definition: pgbench.h:61
@ PGBT_NO_VALUE
Definition: pgbench.h:36
@ PGBT_INT
Definition: pgbench.h:38
@ PGBT_NULL
Definition: pgbench.h:37
@ PGBT_DOUBLE
Definition: pgbench.h:39
@ PGBT_BOOLEAN
Definition: pgbench.h:40
PgBenchFunction
Definition: pgbench.h:66
@ PGBENCH_DIV
Definition: pgbench.h:70
@ PGBENCH_AND
Definition: pgbench.h:87
@ PGBENCH_DOUBLE
Definition: pgbench.h:77
@ PGBENCH_LT
Definition: pgbench.h:98
@ PGBENCH_LN
Definition: pgbench.h:80
@ PGBENCH_RANDOM_EXPONENTIAL
Definition: pgbench.h:84
@ PGBENCH_RSHIFT
Definition: pgbench.h:94
@ PGBENCH_DEBUG
Definition: pgbench.h:72
@ PGBENCH_MOD
Definition: pgbench.h:71
@ PGBENCH_GREATEST
Definition: pgbench.h:75
@ PGBENCH_BITXOR
Definition: pgbench.h:92
@ PGBENCH_RANDOM_ZIPFIAN
Definition: pgbench.h:85
@ PGBENCH_INT
Definition: pgbench.h:76
@ PGBENCH_NE
Definition: pgbench.h:96
@ PGBENCH_OR
Definition: pgbench.h:88
@ PGBENCH_LE
Definition: pgbench.h:97
@ PGBENCH_EXP
Definition: pgbench.h:81
@ PGBENCH_PI
Definition: pgbench.h:78
@ PGBENCH_ADD
Definition: pgbench.h:67
@ PGBENCH_EQ
Definition: pgbench.h:95
@ PGBENCH_LSHIFT
Definition: pgbench.h:93
@ PGBENCH_RANDOM
Definition: pgbench.h:82
@ PGBENCH_POW
Definition: pgbench.h:86
@ PGBENCH_IS
Definition: pgbench.h:99
@ PGBENCH_SUB
Definition: pgbench.h:68
@ PGBENCH_HASH_MURMUR2
Definition: pgbench.h:102
@ PGBENCH_ABS
Definition: pgbench.h:73
@ PGBENCH_BITOR
Definition: pgbench.h:91
@ PGBENCH_SQRT
Definition: pgbench.h:79
@ PGBENCH_LEAST
Definition: pgbench.h:74
@ PGBENCH_PERMUTE
Definition: pgbench.h:103
@ PGBENCH_HASH_FNV1A
Definition: pgbench.h:101
@ PGBENCH_NOT
Definition: pgbench.h:89
@ PGBENCH_BITAND
Definition: pgbench.h:90
@ PGBENCH_RANDOM_GAUSSIAN
Definition: pgbench.h:83
@ PGBENCH_MUL
Definition: pgbench.h:69
@ PGBENCH_CASE
Definition: pgbench.h:100
int expr_yyparse(PgBenchExpr **expr_parse_result_p, yyscan_t yyscanner)
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define pqsignal
Definition: port.h:531
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)
Definition: pgstrcasecmp.c:36
#define sprintf
Definition: port.h:241
#define snprintf
Definition: port.h:239
const char * get_progname(const char *argv0)
Definition: path.c:652
#define qsort(a, b, c, d)
Definition: port.h:479
#define printf(...)
Definition: port.h:245
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:52
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:235
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:72
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
char * c
static int fd(const char *x, int i)
Definition: preproc-init.c:105
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
PsqlScanResult
Definition: psqlscan.h:31
@ PSCAN_BACKSLASH
Definition: psqlscan.h:33
@ PSCAN_EOL
Definition: psqlscan.h:35
@ PSCAN_INCOMPLETE
Definition: psqlscan.h:34
enum _promptStatus promptStatus_t
void psql_scan_get_location(PsqlScanState state, int *lineno, int *offset)
Definition: psqlscan.l:1335
void psql_scan_destroy(PsqlScanState state)
Definition: psqlscan.l:1022
PsqlScanResult psql_scan(PsqlScanState state, PQExpBuffer query_buf, promptStatus_t *prompt)
Definition: psqlscan.l:1121
PsqlScanState psql_scan_create(const PsqlScanCallbacks *callbacks)
Definition: psqlscan.l:1001
void psql_scan_setup(PsqlScanState state, const char *line, int line_len, int encoding, bool std_strings)
Definition: psqlscan.l:1059
void psql_scan_finish(PsqlScanState state)
Definition: psqlscan.l:1248
void pg_usleep(long microsec)
Definition: signal.c:53
char * simple_prompt(const char *prompt, bool echo)
Definition: sprompt.c:38
static void error(void)
Definition: sql-dyntest.c:147
static char * password
Definition: streamutil.c:51
PGconn * conn
Definition: streamutil.c:52
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:313
const char * desc
Definition: pgbench.c:777
const char * name
Definition: pgbench.c:776
const char * script
Definition: pgbench.c:778
int64 cnt
Definition: pgbench.c:638
int id
Definition: pgbench.c:600
pg_time_usec_t txn_scheduled
Definition: pgbench.c:618
pg_time_usec_t stmt_begin
Definition: pgbench.c:621
int command
Definition: pgbench.c:611
pg_time_usec_t sleep_until
Definition: pgbench.c:619
int use_file
Definition: pgbench.c:610
ConditionalStack cstack
Definition: pgbench.c:602
pg_prng_state random_state
Definition: pgbench.c:633
pg_time_usec_t txn_begin
Definition: pgbench.c:620
Variables variables
Definition: pgbench.c:615
EStatus estatus
Definition: pgbench.c:630
int num_syncs
Definition: pgbench.c:612
PGconn * con
Definition: pgbench.c:599
pg_prng_state cs_func_rs
Definition: pgbench.c:608
uint32 tries
Definition: pgbench.c:634
bool ** prepared
Definition: pgbench.c:624
ConnectionStateEnum state
Definition: pgbench.c:601
int64 retries
Definition: pgbench.c:753
char * varprefix
Definition: pgbench.c:750
int type
Definition: pgbench.c:745
PQExpBufferData lines
Definition: pgbench.c:743
MetaCommand meta
Definition: pgbench.c:746
SimpleStats stats
Definition: pgbench.c:752
PgBenchExpr * expr
Definition: pgbench.c:751
int64 failures
Definition: pgbench.c:754
char * argv[MAX_ARGS]
Definition: pgbench.c:748
char * first_line
Definition: pgbench.c:744
int argc
Definition: pgbench.c:747
char * prepname
Definition: pgbench.c:749
const char * desc
Definition: pgbench.c:759
int weight
Definition: pgbench.c:760
Command ** commands
Definition: pgbench.c:761
StatsData stats
Definition: pgbench.c:762
PgBenchValue constant
Definition: pgbench.h:115
char * varname
Definition: pgbench.h:118
PgBenchFunction function
Definition: pgbench.h:122
PgBenchExprType etype
Definition: pgbench.h:112
struct PgBenchExpr::@36::@37 variable
union PgBenchExpr::@36 u
PgBenchValueType type
Definition: pgbench.h:46
bool bval
Definition: pgbench.h:51
union PgBenchValue::@35 u
int64 ival
Definition: pgbench.h:49
double dval
Definition: pgbench.h:50
int64 count
Definition: pgbench.c:359
double sum
Definition: pgbench.c:362
double min
Definition: pgbench.c:360
double max
Definition: pgbench.c:361
double sum2
Definition: pgbench.c:363
int64 serialization_failures
Definition: pgbench.c:436
int64 cnt
Definition: pgbench.c:426
int64 retried
Definition: pgbench.c:432
int64 deadlock_failures
Definition: pgbench.c:439
int64 skipped
Definition: pgbench.c:428
pg_time_usec_t start_time
Definition: pgbench.c:379
SimpleStats lag
Definition: pgbench.c:443
int64 retries
Definition: pgbench.c:430
SimpleStats latency
Definition: pgbench.c:442
pg_time_usec_t create_time
Definition: pgbench.c:666
CState * state
Definition: pgbench.c:650
int tid
Definition: pgbench.c:648
int nstate
Definition: pgbench.c:651
int64 throttle_trigger
Definition: pgbench.c:662
pg_prng_state ts_throttle_rs
Definition: pgbench.c:659
pg_time_usec_t conn_duration
Definition: pgbench.c:669
pg_prng_state ts_choose_rs
Definition: pgbench.c:658
FILE * logfile
Definition: pgbench.c:663
StatsData stats
Definition: pgbench.c:672
THREAD_T thread
Definition: pgbench.c:649
pg_time_usec_t bench_start
Definition: pgbench.c:668
pg_prng_state ts_sample_rs
Definition: pgbench.c:660
int64 latency_late
Definition: pgbench.c:673
pg_time_usec_t started_time
Definition: pgbench.c:667
PgBenchValue value
Definition: pgbench.c:327
char * name
Definition: pgbench.c:325
char * svalue
Definition: pgbench.c:326
Variable * vars
Definition: pgbench.c:335
int nvars
Definition: pgbench.c:336
bool vars_sorted
Definition: pgbench.c:345
int max_vars
Definition: pgbench.c:343
Definition: type.h:96
int maxfd
Definition: pgbench.c:111
fd_set fds
Definition: pgbench.c:112
Definition: regguts.h:323
Definition: regcomp.c:282
const char * get_user_name_or_exit(const char *progname)
Definition: username.c:74
const char * type
const char * name
#define EINTR
Definition: win32_port.h:364
#define SIGALRM
Definition: win32_port.h:164
#define select(n, r, w, e, timeout)
Definition: win32_port.h:503
int gettimeofday(struct timeval *tp, void *tzp)
static char chars[TZ_MAX_CHARS]
Definition: zic.c:401