PostgreSQL Source Code  git master
pgbench.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <signal.h>
#include <time.h>
#include <sys/resource.h>
#include <sys/select.h>
#include "common/int.h"
#include "common/logging.h"
#include "common/pg_prng.h"
#include "common/string.h"
#include "common/username.h"
#include "fe_utils/cancel.h"
#include "fe_utils/conditional.h"
#include "fe_utils/option_utils.h"
#include "fe_utils/string_utils.h"
#include "getopt_long.h"
#include "libpq-fe.h"
#include "pgbench.h"
#include "port/pg_bitutils.h"
#include "portability/instr_time.h"
#include "port/pg_pthread.h"
Include dependency graph for pgbench.c:

Go to the source code of this file.

Data Structures

struct  socket_set
 
struct  Variable
 
struct  Variables
 
struct  SimpleStats
 
struct  StatsData
 
struct  CState
 
struct  TState
 
struct  Command
 
struct  ParsedScript
 
struct  BuiltinScript
 

Macros

#define POLL_USING_SELECT
 
#define M_PI   3.14159265358979323846
 
#define ERRCODE_T_R_SERIALIZATION_FAILURE   "40001"
 
#define ERRCODE_T_R_DEADLOCK_DETECTED   "40P01"
 
#define ERRCODE_UNDEFINED_TABLE   "42P01"
 
#define FNV_PRIME   UINT64CONST(0x100000001b3)
 
#define FNV_OFFSET_BASIS   UINT64CONST(0xcbf29ce484222325)
 
#define MM2_MUL   UINT64CONST(0xc6a4a7935bd1e995)
 
#define MM2_MUL_TIMES_8   UINT64CONST(0x35253c9ade8f4ca8)
 
#define MM2_ROT   47
 
#define SOCKET_WAIT_METHOD   "select"
 
#define THREAD_T   pthread_t
 
#define THREAD_FUNC_RETURN_TYPE   void *
 
#define THREAD_FUNC_RETURN   return NULL
 
#define THREAD_FUNC_CC
 
#define THREAD_CREATE(handle, function, arg)    pthread_create((handle), NULL, (function), (arg))
 
#define THREAD_JOIN(handle)    pthread_join((handle), NULL)
 
#define THREAD_BARRIER_T   pthread_barrier_t
 
#define THREAD_BARRIER_INIT(barrier, n)    pthread_barrier_init((barrier), NULL, (n))
 
#define THREAD_BARRIER_WAIT(barrier)   pthread_barrier_wait((barrier))
 
#define THREAD_BARRIER_DESTROY(barrier)   pthread_barrier_destroy((barrier))
 
#define DEFAULT_INIT_STEPS   "dtgvp" /* default -I setting */
 
#define ALL_INIT_STEPS   "dtgGvpf" /* all possible steps */
 
#define LOG_STEP_SECONDS   5 /* seconds between log messages */
 
#define DEFAULT_NXACTS   10 /* default nxacts */
 
#define MIN_GAUSSIAN_PARAM   2.0 /* minimum parameter for gauss */
 
#define MIN_ZIPFIAN_PARAM   1.001 /* minimum parameter for zipfian */
 
#define MAX_ZIPFIAN_PARAM   1000.0 /* maximum parameter for zipfian */
 
#define nbranches
 
#define ntellers   10
 
#define naccounts   100000
 
#define SCALE_32BIT_THRESHOLD   20000
 
#define WSEP   '@' /* weight separator */
 
#define VARIABLES_ALLOC_MARGIN   8
 
#define MAX_SCRIPTS   128 /* max number of SQL scripts allowed */
 
#define SHELL_COMMAND_SIZE   256 /* maximum size allowed for shell command */
 
#define SQL_COMMAND   1
 
#define META_COMMAND   2
 
#define MAX_ARGS   256
 
#define PG_TIME_GET_DOUBLE(t)   (0.000001 * (t))
 
#define PARAMS_ARRAY_SIZE   7
 
#define MAX_FARGS   16
 
#define COMMANDS_ALLOC_NUM   128
 

Typedefs

typedef struct socket_set socket_set
 
typedef struct SimpleStats SimpleStats
 
typedef int64 pg_time_usec_t
 
typedef struct StatsData StatsData
 
typedef enum EStatus EStatus
 
typedef enum TStatus TStatus
 
typedef enum MetaCommand MetaCommand
 
typedef enum QueryMode QueryMode
 
typedef struct Command Command
 
typedef struct ParsedScript ParsedScript
 
typedef struct BuiltinScript BuiltinScript
 
typedef void(* initRowMethod) (PQExpBufferData *sql, int64 curr)
 

Enumerations

enum  partition_method_t { PART_NONE , PART_RANGE , PART_HASH }
 
enum  EStatus {
  ESTATUS_NO_ERROR = 0 , ESTATUS_META_COMMAND_ERROR , ESTATUS_SERIALIZATION_ERROR , ESTATUS_DEADLOCK_ERROR ,
  ESTATUS_OTHER_SQL_ERROR
}
 
enum  TStatus { TSTATUS_IDLE , TSTATUS_IN_BLOCK , TSTATUS_CONN_ERROR , TSTATUS_OTHER_ERROR }
 
enum  ConnectionStateEnum {
  CSTATE_CHOOSE_SCRIPT , CSTATE_START_TX , CSTATE_PREPARE_THROTTLE , CSTATE_THROTTLE ,
  CSTATE_START_COMMAND , CSTATE_WAIT_RESULT , CSTATE_SLEEP , CSTATE_END_COMMAND ,
  CSTATE_SKIP_COMMAND , CSTATE_ERROR , CSTATE_WAIT_ROLLBACK_RESULT , CSTATE_RETRY ,
  CSTATE_FAILURE , CSTATE_END_TX , CSTATE_ABORTED , CSTATE_FINISHED
}
 
enum  MetaCommand {
  META_NONE , META_SET , META_SETSHELL , META_SHELL ,
  META_SLEEP , META_GSET , META_ASET , META_IF ,
  META_ELIF , META_ELSE , META_ENDIF , META_STARTPIPELINE ,
  META_SYNCPIPELINE , META_ENDPIPELINE
}
 
enum  QueryMode { QUERY_SIMPLE , QUERY_EXTENDED , QUERY_PREPARED , NUM_QUERYMODE }
 

Functions

static void setNullValue (PgBenchValue *pv)
 
static void setBoolValue (PgBenchValue *pv, bool bval)
 
static void setIntValue (PgBenchValue *pv, int64 ival)
 
static void setDoubleValue (PgBenchValue *pv, double dval)
 
static bool evaluateExpr (CState *st, PgBenchExpr *expr, PgBenchValue *retval)
 
static ConnectionStateEnum executeMetaCommand (CState *st, pg_time_usec_t *now)
 
static void doLog (TState *thread, CState *st, StatsData *agg, bool skipped, double latency, double lag)
 
static void processXactStats (TState *thread, CState *st, pg_time_usec_t *now, bool skipped, StatsData *agg)
 
static void addScript (const ParsedScript *script)
 
static THREAD_FUNC_RETURN_TYPE THREAD_FUNC_CC threadRun (void *arg)
 
static void finishCon (CState *st)
 
static void setalarm (int seconds)
 
static socket_setalloc_socket_set (int count)
 
static void free_socket_set (socket_set *sa)
 
static void clear_socket_set (socket_set *sa)
 
static void add_socket_to_set (socket_set *sa, int fd, int idx)
 
static int wait_on_socket_set (socket_set *sa, int64 usecs)
 
static bool socket_has_input (socket_set *sa, int fd, int idx)
 
static pg_time_usec_t pg_time_now (void)
 
static void pg_time_now_lazy (pg_time_usec_t *now)
 
static void usage (void)
 
static bool is_an_int (const char *str)
 
bool strtoint64 (const char *str, bool errorOK, int64 *result)
 
bool strtodouble (const char *str, bool errorOK, double *dv)
 
static void initRandomState (pg_prng_state *state)
 
static int64 getrand (pg_prng_state *state, int64 min, int64 max)
 
static int64 getExponentialRand (pg_prng_state *state, int64 min, int64 max, double parameter)
 
static int64 getGaussianRand (pg_prng_state *state, int64 min, int64 max, double parameter)
 
static int64 getPoissonRand (pg_prng_state *state, double center)
 
static int64 computeIterativeZipfian (pg_prng_state *state, int64 n, double s)
 
static int64 getZipfianRand (pg_prng_state *state, int64 min, int64 max, double s)
 
static int64 getHashFnv1a (int64 val, uint64 seed)
 
static int64 getHashMurmur2 (int64 val, uint64 seed)
 
static int64 permute (const int64 val, const int64 isize, const int64 seed)
 
static void initSimpleStats (SimpleStats *ss)
 
static void addToSimpleStats (SimpleStats *ss, double val)
 
static void mergeSimpleStats (SimpleStats *acc, SimpleStats *ss)
 
static void initStats (StatsData *sd, pg_time_usec_t start)
 
static void accumStats (StatsData *stats, bool skipped, double lat, double lag, EStatus estatus, int64 tries)
 
static void executeStatement (PGconn *con, const char *sql)
 
static void tryExecuteStatement (PGconn *con, const char *sql)
 
static PGconndoConnect (void)
 
static int compareVariableNames (const void *v1, const void *v2)
 
static VariablelookupVariable (Variables *variables, char *name)
 
static char * getVariable (Variables *variables, char *name)
 
static bool makeVariableValue (Variable *var)
 
static bool valid_variable_name (const char *name)
 
static void enlargeVariables (Variables *variables, int needed)
 
static VariablelookupCreateVariable (Variables *variables, const char *context, char *name)
 
static bool putVariable (Variables *variables, const char *context, char *name, const char *value)
 
static bool putVariableValue (Variables *variables, const char *context, char *name, const PgBenchValue *value)
 
static bool putVariableInt (Variables *variables, const char *context, char *name, int64 value)
 
static char * parseVariable (const char *sql, int *eaten)
 
static char * replaceVariable (char **sql, char *param, int len, char *value)
 
static char * assignVariables (Variables *variables, char *sql)
 
static void getQueryParams (Variables *variables, const Command *command, const char **params)
 
static char * valueTypeName (PgBenchValue *pval)
 
static bool coerceToBool (PgBenchValue *pval, bool *bval)
 
static bool valueTruth (PgBenchValue *pval)
 
static bool coerceToInt (PgBenchValue *pval, int64 *ival)
 
static bool coerceToDouble (PgBenchValue *pval, double *dval)
 
static bool isLazyFunc (PgBenchFunction func)
 
static bool evalLazyFunc (CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
 
static bool evalStandardFunc (CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
 
static bool evalFunc (CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
 
static MetaCommand getMetaCommand (const char *cmd)
 
static bool runShellCommand (Variables *variables, char *variable, char **argv, int argc)
 
static void commandFailed (CState *st, const char *cmd, const char *message)
 
static void commandError (CState *st, const char *message)
 
static int chooseScript (TState *thread)
 
static void allocCStatePrepared (CState *st)
 
static void prepareCommand (CState *st, int command_num)
 
static void prepareCommandsInPipeline (CState *st)
 
static bool sendCommand (CState *st, Command *command)
 
static EStatus getSQLErrorStatus (const char *sqlState)
 
static bool canRetryError (EStatus estatus)
 
static bool readCommandResponse (CState *st, MetaCommand meta, char *varprefix)
 
static bool evaluateSleep (Variables *variables, int argc, char **argv, int *usecs)
 
static bool doRetry (CState *st, pg_time_usec_t *now)
 
static int discardUntilSync (CState *st)
 
static TStatus getTransactionStatus (PGconn *con)
 
static void printVerboseErrorMessages (CState *st, pg_time_usec_t *now, bool is_retry)
 
static void advanceConnectionState (TState *thread, CState *st, StatsData *agg)
 
static int64 getFailures (const StatsData *stats)
 
static const char * getResultString (bool skipped, EStatus estatus)
 
static void disconnect_all (CState *state, int length)
 
static void initDropTables (PGconn *con)
 
static void createPartitions (PGconn *con)
 
static void initCreateTables (PGconn *con)
 
static void initTruncateTables (PGconn *con)
 
static void initBranch (PQExpBufferData *sql, int64 curr)
 
static void initTeller (PQExpBufferData *sql, int64 curr)
 
static void initAccount (PQExpBufferData *sql, int64 curr)
 
static void initPopulateTable (PGconn *con, const char *table, int64 base, initRowMethod init_row)
 
static void initGenerateDataClientSide (PGconn *con)
 
static void initGenerateDataServerSide (PGconn *con)
 
static void initVacuum (PGconn *con)
 
static void initCreatePKeys (PGconn *con)
 
static void initCreateFKeys (PGconn *con)
 
static void checkInitSteps (const char *initialize_steps)
 
static void runInitSteps (const char *initialize_steps)
 
static void GetTableInfo (PGconn *con, bool scale_given)
 
static bool parseQuery (Command *cmd)
 
void syntax_error (const char *source, int lineno, const char *line, const char *command, const char *msg, const char *more, int column)
 
static char * skip_sql_comments (char *sql_command)
 
static Commandcreate_sql_command (PQExpBuffer buf, const char *source)
 
static void free_command (Command *command)
 
static void postprocess_sql_command (Command *my_command)
 
static Commandprocess_backslash_command (PsqlScanState sstate, const char *source)
 
static void ConditionError (const char *desc, int cmdn, const char *msg)
 
static void CheckConditional (const ParsedScript *ps)
 
static void ParseScript (const char *script, const char *desc, int weight)
 
static char * read_file_contents (FILE *fd)
 
static void process_file (const char *filename, int weight)
 
static void process_builtin (const BuiltinScript *bi, int weight)
 
static void listAvailableScripts (void)
 
static const BuiltinScriptfindBuiltin (const char *name)
 
static int parseScriptWeight (const char *option, char **script)
 
static void printProgressReport (TState *threads, int64 test_start, pg_time_usec_t now, StatsData *last, int64 *last_report)
 
static void printSimpleStats (const char *prefix, SimpleStats *ss)
 
static void printVersion (PGconn *con)
 
static void printResults (StatsData *total, pg_time_usec_t total_duration, pg_time_usec_t conn_total_duration, pg_time_usec_t conn_elapsed_duration, int64 latency_late)
 
static bool set_random_seed (const char *seed)
 
int main (int argc, char **argv)
 
static void handle_sig_alarm (SIGNAL_ARGS)
 

Variables

int nxacts = 0
 
int duration = 0
 
int64 end_time = 0
 
int scale = 1
 
int fillfactor = 100
 
bool unlogged_tables = false
 
double sample_rate = 0.0
 
double throttle_delay = 0
 
int64 latency_limit = 0
 
char * tablespace = NULL
 
char * index_tablespace = NULL
 
static int partitions = 0
 
static partition_method_t partition_method = PART_NONE
 
static const char *const PARTITION_METHOD [] = {"none", "range", "hash"}
 
int64 random_seed = -1
 
bool use_log
 
bool use_quiet
 
int agg_interval
 
bool per_script_stats = false
 
int progress = 0
 
bool progress_timestamp = false
 
int nclients = 1
 
int nthreads = 1
 
bool is_connect
 
bool report_per_command = false
 
int main_pid
 
uint32 max_tries = 1
 
bool failures_detailed = false
 
const char * pghost = NULL
 
const char * pgport = NULL
 
const char * username = NULL
 
const char * dbName = NULL
 
char * logfile_prefix = NULL
 
const char * progname
 
volatile sig_atomic_t timer_exceeded = false
 
pg_time_usec_t epoch_shift
 
static pg_prng_state base_random_sequence
 
static THREAD_BARRIER_T barrier
 
static QueryMode querymode = QUERY_SIMPLE
 
static const char *const QUERYMODE [] = {"simple", "extended", "prepared"}
 
static ParsedScript sql_script [MAX_SCRIPTS]
 
static int num_scripts
 
static int64 total_weight = 0
 
static bool verbose_errors = false
 
static bool exit_on_abort = false
 
static const BuiltinScript builtin_script []
 
static const PsqlScanCallbacks pgbench_callbacks
 

Macro Definition Documentation

◆ ALL_INIT_STEPS

#define ALL_INIT_STEPS   "dtgGvpf" /* all possible steps */

Definition at line 163 of file pgbench.c.

◆ COMMANDS_ALLOC_NUM

#define COMMANDS_ALLOC_NUM   128

◆ DEFAULT_INIT_STEPS

#define DEFAULT_INIT_STEPS   "dtgvp" /* default -I setting */

Definition at line 162 of file pgbench.c.

◆ DEFAULT_NXACTS

#define DEFAULT_NXACTS   10 /* default nxacts */

Definition at line 166 of file pgbench.c.

◆ ERRCODE_T_R_DEADLOCK_DETECTED

#define ERRCODE_T_R_DEADLOCK_DETECTED   "40P01"

Definition at line 77 of file pgbench.c.

◆ ERRCODE_T_R_SERIALIZATION_FAILURE

#define ERRCODE_T_R_SERIALIZATION_FAILURE   "40001"

Definition at line 76 of file pgbench.c.

◆ ERRCODE_UNDEFINED_TABLE

#define ERRCODE_UNDEFINED_TABLE   "42P01"

Definition at line 78 of file pgbench.c.

◆ FNV_OFFSET_BASIS

#define FNV_OFFSET_BASIS   UINT64CONST(0xcbf29ce484222325)

Definition at line 84 of file pgbench.c.

◆ FNV_PRIME

#define FNV_PRIME   UINT64CONST(0x100000001b3)

Definition at line 83 of file pgbench.c.

◆ LOG_STEP_SECONDS

#define LOG_STEP_SECONDS   5 /* seconds between log messages */

Definition at line 165 of file pgbench.c.

◆ M_PI

#define M_PI   3.14159265358979323846

Definition at line 73 of file pgbench.c.

◆ MAX_ARGS

#define MAX_ARGS   256

Definition at line 684 of file pgbench.c.

◆ MAX_FARGS

#define MAX_FARGS   16

Definition at line 2240 of file pgbench.c.

◆ MAX_SCRIPTS

#define MAX_SCRIPTS   128 /* max number of SQL scripts allowed */

Definition at line 346 of file pgbench.c.

◆ MAX_ZIPFIAN_PARAM

#define MAX_ZIPFIAN_PARAM   1000.0 /* maximum parameter for zipfian */

Definition at line 171 of file pgbench.c.

◆ META_COMMAND

#define META_COMMAND   2

Definition at line 678 of file pgbench.c.

◆ MIN_GAUSSIAN_PARAM

#define MIN_GAUSSIAN_PARAM   2.0 /* minimum parameter for gauss */

Definition at line 168 of file pgbench.c.

◆ MIN_ZIPFIAN_PARAM

#define MIN_ZIPFIAN_PARAM   1.001 /* minimum parameter for zipfian */

Definition at line 170 of file pgbench.c.

◆ MM2_MUL

#define MM2_MUL   UINT64CONST(0xc6a4a7935bd1e995)

Definition at line 85 of file pgbench.c.

◆ MM2_MUL_TIMES_8

#define MM2_MUL_TIMES_8   UINT64CONST(0x35253c9ade8f4ca8)

Definition at line 86 of file pgbench.c.

◆ MM2_ROT

#define MM2_ROT   47

Definition at line 87 of file pgbench.c.

◆ naccounts

#define naccounts   100000

Definition at line 245 of file pgbench.c.

◆ nbranches

#define nbranches
Value:
1 /* Makes little sense to change this. Change
* -s instead */

Definition at line 243 of file pgbench.c.

◆ ntellers

#define ntellers   10

Definition at line 244 of file pgbench.c.

◆ PARAMS_ARRAY_SIZE

#define PARAMS_ARRAY_SIZE   7

◆ PG_TIME_GET_DOUBLE

#define PG_TIME_GET_DOUBLE (   t)    (0.000001 * (t))

Definition at line 866 of file pgbench.c.

◆ POLL_USING_SELECT

#define POLL_USING_SELECT

Definition at line 52 of file pgbench.c.

◆ SCALE_32BIT_THRESHOLD

#define SCALE_32BIT_THRESHOLD   20000

Definition at line 254 of file pgbench.c.

◆ SHELL_COMMAND_SIZE

#define SHELL_COMMAND_SIZE   256 /* maximum size allowed for shell command */

Definition at line 347 of file pgbench.c.

◆ SOCKET_WAIT_METHOD

#define SOCKET_WAIT_METHOD   "select"

Definition at line 106 of file pgbench.c.

◆ SQL_COMMAND

#define SQL_COMMAND   1

Definition at line 677 of file pgbench.c.

◆ THREAD_BARRIER_DESTROY

#define THREAD_BARRIER_DESTROY (   barrier)    pthread_barrier_destroy((barrier))

Definition at line 155 of file pgbench.c.

◆ THREAD_BARRIER_INIT

#define THREAD_BARRIER_INIT (   barrier,
 
)     pthread_barrier_init((barrier), NULL, (n))

Definition at line 152 of file pgbench.c.

◆ THREAD_BARRIER_T

#define THREAD_BARRIER_T   pthread_barrier_t

Definition at line 151 of file pgbench.c.

◆ THREAD_BARRIER_WAIT

#define THREAD_BARRIER_WAIT (   barrier)    pthread_barrier_wait((barrier))

Definition at line 154 of file pgbench.c.

◆ THREAD_CREATE

#define THREAD_CREATE (   handle,
  function,
  arg 
)     pthread_create((handle), NULL, (function), (arg))

Definition at line 147 of file pgbench.c.

◆ THREAD_FUNC_CC

#define THREAD_FUNC_CC

Definition at line 146 of file pgbench.c.

◆ THREAD_FUNC_RETURN

#define THREAD_FUNC_RETURN   return NULL

Definition at line 145 of file pgbench.c.

◆ THREAD_FUNC_RETURN_TYPE

#define THREAD_FUNC_RETURN_TYPE   void *

Definition at line 144 of file pgbench.c.

◆ THREAD_JOIN

#define THREAD_JOIN (   handle)     pthread_join((handle), NULL)

Definition at line 149 of file pgbench.c.

◆ THREAD_T

#define THREAD_T   pthread_t

Definition at line 143 of file pgbench.c.

◆ VARIABLES_ALLOC_MARGIN

#define VARIABLES_ALLOC_MARGIN   8

Definition at line 309 of file pgbench.c.

◆ WSEP

#define WSEP   '@' /* weight separator */

Definition at line 301 of file pgbench.c.

Typedef Documentation

◆ BuiltinScript

typedef struct BuiltinScript BuiltinScript

◆ Command

typedef struct Command Command

◆ EStatus

typedef enum EStatus EStatus

◆ initRowMethod

typedef void(* initRowMethod) (PQExpBufferData *sql, int64 curr)

Definition at line 842 of file pgbench.c.

◆ MetaCommand

typedef enum MetaCommand MetaCommand

◆ ParsedScript

typedef struct ParsedScript ParsedScript

◆ pg_time_usec_t

typedef int64 pg_time_usec_t

Definition at line 369 of file pgbench.c.

◆ QueryMode

typedef enum QueryMode QueryMode

◆ SimpleStats

typedef struct SimpleStats SimpleStats

◆ socket_set

typedef struct socket_set socket_set

◆ StatsData

typedef struct StatsData StatsData

◆ TStatus

typedef enum TStatus TStatus

Enumeration Type Documentation

◆ ConnectionStateEnum

Enumerator
CSTATE_CHOOSE_SCRIPT 
CSTATE_START_TX 
CSTATE_PREPARE_THROTTLE 
CSTATE_THROTTLE 
CSTATE_START_COMMAND 
CSTATE_WAIT_RESULT 
CSTATE_SLEEP 
CSTATE_END_COMMAND 
CSTATE_SKIP_COMMAND 
CSTATE_ERROR 
CSTATE_WAIT_ROLLBACK_RESULT 
CSTATE_RETRY 
CSTATE_FAILURE 
CSTATE_END_TX 
CSTATE_ABORTED 
CSTATE_FINISHED 

Definition at line 484 of file pgbench.c.

486 {
487  /*
488  * The client must first choose a script to execute. Once chosen, it can
489  * either be throttled (state CSTATE_PREPARE_THROTTLE under --rate), start
490  * right away (state CSTATE_START_TX) or not start at all if the timer was
491  * exceeded (state CSTATE_FINISHED).
492  */
494 
495  /*
496  * CSTATE_START_TX performs start-of-transaction processing. Establishes
497  * a new connection for the transaction in --connect mode, records the
498  * transaction start time, and proceed to the first command.
499  *
500  * Note: once a script is started, it will either error or run till its
501  * end, where it may be interrupted. It is not interrupted while running,
502  * so pgbench --time is to be understood as tx are allowed to start in
503  * that time, and will finish when their work is completed.
504  */
506 
507  /*
508  * In CSTATE_PREPARE_THROTTLE state, we calculate when to begin the next
509  * transaction, and advance to CSTATE_THROTTLE. CSTATE_THROTTLE state
510  * sleeps until that moment, then advances to CSTATE_START_TX, or
511  * CSTATE_FINISHED if the next transaction would start beyond the end of
512  * the run.
513  */
516 
517  /*
518  * We loop through these states, to process each command in the script:
519  *
520  * CSTATE_START_COMMAND starts the execution of a command. On a SQL
521  * command, the command is sent to the server, and we move to
522  * CSTATE_WAIT_RESULT state unless in pipeline mode. On a \sleep
523  * meta-command, the timer is set, and we enter the CSTATE_SLEEP state to
524  * wait for it to expire. Other meta-commands are executed immediately. If
525  * the command about to start is actually beyond the end of the script,
526  * advance to CSTATE_END_TX.
527  *
528  * CSTATE_WAIT_RESULT waits until we get a result set back from the server
529  * for the current command.
530  *
531  * CSTATE_SLEEP waits until the end of \sleep.
532  *
533  * CSTATE_END_COMMAND records the end-of-command timestamp, increments the
534  * command counter, and loops back to CSTATE_START_COMMAND state.
535  *
536  * CSTATE_SKIP_COMMAND is used by conditional branches which are not
537  * executed. It quickly skip commands that do not need any evaluation.
538  * This state can move forward several commands, till there is something
539  * to do or the end of the script.
540  */
543  CSTATE_SLEEP,
546 
547  /*
548  * States for failed commands.
549  *
550  * If the SQL/meta command fails, in CSTATE_ERROR clean up after an error:
551  * (1) clear the conditional stack; (2) if we have an unterminated
552  * (possibly failed) transaction block, send the rollback command to the
553  * server and wait for the result in CSTATE_WAIT_ROLLBACK_RESULT. If
554  * something goes wrong with rolling back, go to CSTATE_ABORTED.
555  *
556  * But if everything is ok we are ready for future transactions: if this
557  * is a serialization or deadlock error and we can re-execute the
558  * transaction from the very beginning, go to CSTATE_RETRY; otherwise go
559  * to CSTATE_FAILURE.
560  *
561  * In CSTATE_RETRY report an error, set the same parameters for the
562  * transaction execution as in the previous tries and process the first
563  * transaction command in CSTATE_START_COMMAND.
564  *
565  * In CSTATE_FAILURE report a failure, set the parameters for the
566  * transaction execution as they were before the first run of this
567  * transaction (except for a random state) and go to CSTATE_END_TX to
568  * complete this transaction.
569  */
570  CSTATE_ERROR,
572  CSTATE_RETRY,
574 
575  /*
576  * CSTATE_END_TX performs end-of-transaction processing. It calculates
577  * latency, and logs the transaction. In --connect mode, it closes the
578  * current connection.
579  *
580  * Then either starts over in CSTATE_CHOOSE_SCRIPT, or enters
581  * CSTATE_FINISHED if we have no more work to do.
582  */
584 
585  /*
586  * Final states. CSTATE_ABORTED means that the script execution was
587  * aborted because a command failed, CSTATE_FINISHED means success.
588  */
@ CSTATE_START_TX
Definition: pgbench.c:504
@ CSTATE_END_TX
Definition: pgbench.c:582
@ CSTATE_RETRY
Definition: pgbench.c:571
@ CSTATE_FINISHED
Definition: pgbench.c:589
@ CSTATE_SKIP_COMMAND
Definition: pgbench.c:544
@ CSTATE_THROTTLE
Definition: pgbench.c:514
@ CSTATE_FAILURE
Definition: pgbench.c:572
@ CSTATE_START_COMMAND
Definition: pgbench.c:540
@ CSTATE_END_COMMAND
Definition: pgbench.c:543
@ CSTATE_WAIT_RESULT
Definition: pgbench.c:541
@ CSTATE_CHOOSE_SCRIPT
Definition: pgbench.c:492
@ CSTATE_WAIT_ROLLBACK_RESULT
Definition: pgbench.c:570
@ CSTATE_ABORTED
Definition: pgbench.c:588
@ CSTATE_PREPARE_THROTTLE
Definition: pgbench.c:513
@ CSTATE_SLEEP
Definition: pgbench.c:542
@ CSTATE_ERROR
Definition: pgbench.c:569

◆ EStatus

enum EStatus
Enumerator
ESTATUS_NO_ERROR 
ESTATUS_META_COMMAND_ERROR 
ESTATUS_SERIALIZATION_ERROR 
ESTATUS_DEADLOCK_ERROR 
ESTATUS_OTHER_SQL_ERROR 

Definition at line 453 of file pgbench.c.

455 {
456  ESTATUS_NO_ERROR = 0,
458 
459  /* SQL errors */
@ ESTATUS_DEADLOCK_ERROR
Definition: pgbench.c:460
@ ESTATUS_META_COMMAND_ERROR
Definition: pgbench.c:456
@ ESTATUS_OTHER_SQL_ERROR
Definition: pgbench.c:461
@ ESTATUS_NO_ERROR
Definition: pgbench.c:455
@ ESTATUS_SERIALIZATION_ERROR
Definition: pgbench.c:459

◆ MetaCommand

Enumerator
META_NONE 
META_SET 
META_SETSHELL 
META_SHELL 
META_SLEEP 
META_GSET 
META_ASET 
META_IF 
META_ELIF 
META_ELSE 
META_ENDIF 
META_STARTPIPELINE 
META_SYNCPIPELINE 
META_ENDPIPELINE 

Definition at line 686 of file pgbench.c.

688 {
689  META_NONE, /* not a known meta-command */
690  META_SET, /* \set */
691  META_SETSHELL, /* \setshell */
692  META_SHELL, /* \shell */
693  META_SLEEP, /* \sleep */
694  META_GSET, /* \gset */
695  META_ASET, /* \aset */
696  META_IF, /* \if */
697  META_ELIF, /* \elif */
698  META_ELSE, /* \else */
699  META_ENDIF, /* \endif */
700  META_STARTPIPELINE, /* \startpipeline */
701  META_SYNCPIPELINE, /* \syncpipeline */
702  META_ENDPIPELINE, /* \endpipeline */
@ META_ELSE
Definition: pgbench.c:697
@ META_SETSHELL
Definition: pgbench.c:690
@ META_ENDIF
Definition: pgbench.c:698
@ META_SHELL
Definition: pgbench.c:691
@ META_STARTPIPELINE
Definition: pgbench.c:699
@ META_SET
Definition: pgbench.c:689
@ META_ELIF
Definition: pgbench.c:696
@ META_SYNCPIPELINE
Definition: pgbench.c:700
@ META_SLEEP
Definition: pgbench.c:692
@ META_NONE
Definition: pgbench.c:688
@ META_IF
Definition: pgbench.c:695
@ META_ENDPIPELINE
Definition: pgbench.c:701
@ META_ASET
Definition: pgbench.c:694
@ META_GSET
Definition: pgbench.c:693

◆ partition_method_t

Enumerator
PART_NONE 
PART_RANGE 
PART_HASH 

Definition at line 226 of file pgbench.c.

227 {
228  PART_NONE, /* no partitioning */
229  PART_RANGE, /* range partitioning */
230  PART_HASH, /* hash partitioning */
partition_method_t
Definition: pgbench.c:227
@ PART_NONE
Definition: pgbench.c:228
@ PART_RANGE
Definition: pgbench.c:229
@ PART_HASH
Definition: pgbench.c:230

◆ QueryMode

enum QueryMode
Enumerator
QUERY_SIMPLE 
QUERY_EXTENDED 
QUERY_PREPARED 
NUM_QUERYMODE 

Definition at line 704 of file pgbench.c.

706 {
707  QUERY_SIMPLE, /* simple query */
708  QUERY_EXTENDED, /* extended query */
709  QUERY_PREPARED, /* extended query with prepared statements */
@ QUERY_PREPARED
Definition: pgbench.c:708
@ NUM_QUERYMODE
Definition: pgbench.c:709
@ QUERY_SIMPLE
Definition: pgbench.c:706
@ QUERY_EXTENDED
Definition: pgbench.c:707

◆ TStatus

enum TStatus
Enumerator
TSTATUS_IDLE 
TSTATUS_IN_BLOCK 
TSTATUS_CONN_ERROR 
TSTATUS_OTHER_ERROR 

Definition at line 467 of file pgbench.c.

469 {
470  TSTATUS_IDLE,
@ TSTATUS_CONN_ERROR
Definition: pgbench.c:471
@ TSTATUS_IDLE
Definition: pgbench.c:469
@ TSTATUS_IN_BLOCK
Definition: pgbench.c:470
@ TSTATUS_OTHER_ERROR
Definition: pgbench.c:472

Function Documentation

◆ accumStats()

static void accumStats ( StatsData stats,
bool  skipped,
double  lat,
double  lag,
EStatus  estatus,
int64  tries 
)
static

Definition at line 1449 of file pgbench.c.

1452 {
1453  /* Record the skipped transaction */
1454  if (skipped)
1455  {
1456  /* no latency to record on skipped transactions */
1457  stats->skipped++;
1458  return;
1459  }
1460 
1461  /*
1462  * Record the number of retries regardless of whether the transaction was
1463  * successful or failed.
1464  */
1465  if (tries > 1)
1466  {
1467  stats->retries += (tries - 1);
1468  stats->retried++;
1469  }
1470 
1471  switch (estatus)
1472  {
1473  /* Record the successful transaction */
1474  case ESTATUS_NO_ERROR:
1475  stats->cnt++;
1476 
1477  addToSimpleStats(&stats->latency, lat);
1478 
1479  /* and possibly the same for schedule lag */
1480  if (throttle_delay)
1481  addToSimpleStats(&stats->lag, lag);
1482  break;
1483 
1484  /* Record the failed transaction */
1486  stats->serialization_failures++;
1487  break;
1489  stats->deadlock_failures++;
1490  break;
1491  default:
1492  /* internal error which should never occur */
1493  pg_fatal("unexpected error status: %d", estatus);
1494  }
#define pg_fatal(...)
double throttle_delay
Definition: pgbench.c:203
static void addToSimpleStats(SimpleStats *ss, double val)
Definition: pgbench.c:1401
int64 serialization_failures
Definition: pgbench.c:434
int64 cnt
Definition: pgbench.c:424
int64 retried
Definition: pgbench.c:430
int64 deadlock_failures
Definition: pgbench.c:437
int64 skipped
Definition: pgbench.c:426
SimpleStats lag
Definition: pgbench.c:441
int64 retries
Definition: pgbench.c:428
SimpleStats latency
Definition: pgbench.c:440

References addToSimpleStats(), StatsData::cnt, StatsData::deadlock_failures, ESTATUS_DEADLOCK_ERROR, ESTATUS_NO_ERROR, ESTATUS_SERIALIZATION_ERROR, StatsData::lag, StatsData::latency, pg_fatal, StatsData::retried, StatsData::retries, StatsData::serialization_failures, StatsData::skipped, and throttle_delay.

Referenced by doLog(), and processXactStats().

◆ add_socket_to_set()

static void add_socket_to_set ( socket_set sa,
int  fd,
int  idx 
)
static

Definition at line 7870 of file pgbench.c.

7872 {
7873  /* See connect_slot() for background on this code. */
7874 #ifdef WIN32
7875  if (sa->fds.fd_count + 1 >= FD_SETSIZE)
7876  {
7877  pg_log_error("too many concurrent database clients for this platform: %d",
7878  sa->fds.fd_count + 1);
7879  exit(1);
7880  }
7881 #else
7882  if (fd < 0 || fd >= FD_SETSIZE)
7883  {
7884  pg_log_error("socket file descriptor out of range for select(): %d",
7885  fd);
7886  pg_log_error_hint("Try fewer concurrent database clients.");
7887  exit(1);
7888  }
7889 #endif
7890  FD_SET(fd, &sa->fds);
7891  if (fd > sa->maxfd)
7892  sa->maxfd = fd;
exit(1)
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_error_hint(...)
Definition: logging.h:112
static int fd(const char *x, int i)
Definition: preproc-init.c:105

References exit(), fd(), pg_log_error, and pg_log_error_hint.

Referenced by threadRun().

◆ addScript()

static void addScript ( const ParsedScript script)
static

Definition at line 6191 of file pgbench.c.

6193 {
6194  if (script->commands == NULL || script->commands[0] == NULL)
6195  pg_fatal("empty command list for script \"%s\"", script->desc);
6196 
6197  if (num_scripts >= MAX_SCRIPTS)
6198  pg_fatal("at most %d SQL scripts are allowed", MAX_SCRIPTS);
6199 
6200  CheckConditional(script);
6201 
6202  sql_script[num_scripts] = *script;
6203  num_scripts++;
static void CheckConditional(const ParsedScript *ps)
Definition: pgbench.c:5853
#define MAX_SCRIPTS
Definition: pgbench.c:346
static ParsedScript sql_script[MAX_SCRIPTS]
Definition: pgbench.c:763
static int num_scripts
Definition: pgbench.c:764
const char * desc
Definition: pgbench.c:757
Command ** commands
Definition: pgbench.c:759

References CheckConditional(), ParsedScript::commands, ParsedScript::desc, MAX_SCRIPTS, num_scripts, pg_fatal, and sql_script.

Referenced by ParseScript().

◆ addToSimpleStats()

static void addToSimpleStats ( SimpleStats ss,
double  val 
)
static

Definition at line 1401 of file pgbench.c.

1403 {
1404  if (ss->count == 0 || val < ss->min)
1405  ss->min = val;
1406  if (ss->count == 0 || val > ss->max)
1407  ss->max = val;
1408  ss->count++;
1409  ss->sum += val;
1410  ss->sum2 += val * val;
long val
Definition: informix.c:664
int64 count
Definition: pgbench.c:357
double sum
Definition: pgbench.c:360
double min
Definition: pgbench.c:358
double max
Definition: pgbench.c:359
double sum2
Definition: pgbench.c:361

References SimpleStats::count, SimpleStats::max, SimpleStats::min, SimpleStats::sum, SimpleStats::sum2, and val.

Referenced by accumStats(), and advanceConnectionState().

◆ advanceConnectionState()

static void advanceConnectionState ( TState thread,
CState st,
StatsData agg 
)
static

Definition at line 3587 of file pgbench.c.

3589 {
3590 
3591  /*
3592  * gettimeofday() isn't free, so we get the current timestamp lazily the
3593  * first time it's needed, and reuse the same value throughout this
3594  * function after that. This also ensures that e.g. the calculated
3595  * latency reported in the log file and in the totals are the same. Zero
3596  * means "not set yet". Reset "now" when we execute shell commands or
3597  * expressions, which might take a non-negligible amount of time, though.
3598  */
3599  pg_time_usec_t now = 0;
3600 
3601  /*
3602  * Loop in the state machine, until we have to wait for a result from the
3603  * server or have to sleep for throttling or \sleep.
3604  *
3605  * Note: In the switch-statement below, 'break' will loop back here,
3606  * meaning "continue in the state machine". Return is used to return to
3607  * the caller, giving the thread the opportunity to advance another
3608  * client.
3609  */
3610  for (;;)
3611  {
3612  Command *command;
3613 
3614  switch (st->state)
3615  {
3616  /* Select transaction (script) to run. */
3617  case CSTATE_CHOOSE_SCRIPT:
3618  st->use_file = chooseScript(thread);
3620 
3621  /* reset transaction variables to default values */
3622  st->estatus = ESTATUS_NO_ERROR;
3623  st->tries = 1;
3624 
3625  pg_log_debug("client %d executing script \"%s\"",
3626  st->id, sql_script[st->use_file].desc);
3627 
3628  /*
3629  * If time is over, we're done; otherwise, get ready to start
3630  * a new transaction, or to get throttled if that's requested.
3631  */
3634  break;
3635 
3636  /* Start new transaction (script) */
3637  case CSTATE_START_TX:
3639 
3640  /* establish connection if needed, i.e. under --connect */
3641  if (st->con == NULL)
3642  {
3643  pg_time_usec_t start = now;
3644 
3645  if ((st->con = doConnect()) == NULL)
3646  {
3647  /*
3648  * as the bench is already running, we do not abort
3649  * the process
3650  */
3651  pg_log_error("client %d aborted while establishing connection", st->id);
3652  st->state = CSTATE_ABORTED;
3653  break;
3654  }
3655 
3656  /* reset now after connection */
3657  now = pg_time_now();
3658 
3659  thread->conn_duration += now - start;
3660 
3661  /* Reset session-local state */
3662  pg_free(st->prepared);
3663  st->prepared = NULL;
3664  }
3665 
3666  /*
3667  * It is the first try to run this transaction. Remember the
3668  * random state: maybe it will get an error and we will need
3669  * to run it again.
3670  */
3671  st->random_state = st->cs_func_rs;
3672 
3673  /* record transaction start time */
3674  st->txn_begin = now;
3675 
3676  /*
3677  * When not throttling, this is also the transaction's
3678  * scheduled start time.
3679  */
3680  if (!throttle_delay)
3681  st->txn_scheduled = now;
3682 
3683  /* Begin with the first command */
3685  st->command = 0;
3686  break;
3687 
3688  /*
3689  * Handle throttling once per transaction by sleeping.
3690  */
3692 
3693  /*
3694  * Generate a delay such that the series of delays will
3695  * approximate a Poisson distribution centered on the
3696  * throttle_delay time.
3697  *
3698  * If transactions are too slow or a given wait is shorter
3699  * than a transaction, the next transaction will start right
3700  * away.
3701  */
3702  Assert(throttle_delay > 0);
3703 
3704  thread->throttle_trigger +=
3706  st->txn_scheduled = thread->throttle_trigger;
3707 
3708  /*
3709  * If --latency-limit is used, and this slot is already late
3710  * so that the transaction will miss the latency limit even if
3711  * it completed immediately, skip this time slot and loop to
3712  * reschedule.
3713  */
3714  if (latency_limit)
3715  {
3717 
3718  if (thread->throttle_trigger < now - latency_limit)
3719  {
3720  processXactStats(thread, st, &now, true, agg);
3721 
3722  /*
3723  * Finish client if -T or -t was exceeded.
3724  *
3725  * Stop counting skipped transactions under -T as soon
3726  * as the timer is exceeded. Because otherwise it can
3727  * take a very long time to count all of them
3728  * especially when quite a lot of them happen with
3729  * unrealistically high rate setting in -R, which
3730  * would prevent pgbench from ending immediately.
3731  * Because of this behavior, note that there is no
3732  * guarantee that all skipped transactions are counted
3733  * under -T though there is under -t. This is OK in
3734  * practice because it's very unlikely to happen with
3735  * realistic setting.
3736  */
3737  if (timer_exceeded || (nxacts > 0 && st->cnt >= nxacts))
3738  st->state = CSTATE_FINISHED;
3739 
3740  /* Go back to top of loop with CSTATE_PREPARE_THROTTLE */
3741  break;
3742  }
3743  }
3744 
3745  /*
3746  * stop client if next transaction is beyond pgbench end of
3747  * execution; otherwise, throttle it.
3748  */
3749  st->state = end_time > 0 && st->txn_scheduled > end_time ?
3751  break;
3752 
3753  /*
3754  * Wait until it's time to start next transaction.
3755  */
3756  case CSTATE_THROTTLE:
3758 
3759  if (now < st->txn_scheduled)
3760  return; /* still sleeping, nothing to do here */
3761 
3762  /* done sleeping, but don't start transaction if we're done */
3764  break;
3765 
3766  /*
3767  * Send a command to server (or execute a meta-command)
3768  */
3769  case CSTATE_START_COMMAND:
3770  command = sql_script[st->use_file].commands[st->command];
3771 
3772  /*
3773  * Transition to script end processing if done, but close up
3774  * shop if a pipeline is open at this point.
3775  */
3776  if (command == NULL)
3777  {
3778  if (PQpipelineStatus(st->con) == PQ_PIPELINE_OFF)
3779  st->state = CSTATE_END_TX;
3780  else
3781  {
3782  pg_log_error("client %d aborted: end of script reached with pipeline open",
3783  st->id);
3784  st->state = CSTATE_ABORTED;
3785  }
3786 
3787  break;
3788  }
3789 
3790  /* record begin time of next command, and initiate it */
3791  if (report_per_command)
3792  {
3794  st->stmt_begin = now;
3795  }
3796 
3797  /* Execute the command */
3798  if (command->type == SQL_COMMAND)
3799  {
3800  /* disallow \aset and \gset in pipeline mode */
3801  if (PQpipelineStatus(st->con) != PQ_PIPELINE_OFF)
3802  {
3803  if (command->meta == META_GSET)
3804  {
3805  commandFailed(st, "gset", "\\gset is not allowed in pipeline mode");
3806  st->state = CSTATE_ABORTED;
3807  break;
3808  }
3809  else if (command->meta == META_ASET)
3810  {
3811  commandFailed(st, "aset", "\\aset is not allowed in pipeline mode");
3812  st->state = CSTATE_ABORTED;
3813  break;
3814  }
3815  }
3816 
3817  if (!sendCommand(st, command))
3818  {
3819  commandFailed(st, "SQL", "SQL command send failed");
3820  st->state = CSTATE_ABORTED;
3821  }
3822  else
3823  {
3824  /* Wait for results, unless in pipeline mode */
3825  if (PQpipelineStatus(st->con) == PQ_PIPELINE_OFF)
3826  st->state = CSTATE_WAIT_RESULT;
3827  else
3828  st->state = CSTATE_END_COMMAND;
3829  }
3830  }
3831  else if (command->type == META_COMMAND)
3832  {
3833  /*-----
3834  * Possible state changes when executing meta commands:
3835  * - on errors CSTATE_ABORTED
3836  * - on sleep CSTATE_SLEEP
3837  * - else CSTATE_END_COMMAND
3838  */
3839  st->state = executeMetaCommand(st, &now);
3840  if (st->state == CSTATE_ABORTED)
3842  }
3843 
3844  /*
3845  * We're now waiting for an SQL command to complete, or
3846  * finished processing a metacommand, or need to sleep, or
3847  * something bad happened.
3848  */
3849  Assert(st->state == CSTATE_WAIT_RESULT ||
3850  st->state == CSTATE_END_COMMAND ||
3851  st->state == CSTATE_SLEEP ||
3852  st->state == CSTATE_ABORTED);
3853  break;
3854 
3855  /*
3856  * non executed conditional branch
3857  */
3858  case CSTATE_SKIP_COMMAND:
3860  /* quickly skip commands until something to do... */
3861  while (true)
3862  {
3863  command = sql_script[st->use_file].commands[st->command];
3864 
3865  /* cannot reach end of script in that state */
3866  Assert(command != NULL);
3867 
3868  /*
3869  * if this is conditional related, update conditional
3870  * state
3871  */
3872  if (command->type == META_COMMAND &&
3873  (command->meta == META_IF ||
3874  command->meta == META_ELIF ||
3875  command->meta == META_ELSE ||
3876  command->meta == META_ENDIF))
3877  {
3878  switch (conditional_stack_peek(st->cstack))
3879  {
3880  case IFSTATE_FALSE:
3881  if (command->meta == META_IF ||
3882  command->meta == META_ELIF)
3883  {
3884  /* we must evaluate the condition */
3886  }
3887  else if (command->meta == META_ELSE)
3888  {
3889  /* we must execute next command */
3893  st->command++;
3894  }
3895  else if (command->meta == META_ENDIF)
3896  {
3899  if (conditional_active(st->cstack))
3901 
3902  /*
3903  * else state remains in
3904  * CSTATE_SKIP_COMMAND
3905  */
3906  st->command++;
3907  }
3908  break;
3909 
3910  case IFSTATE_IGNORED:
3911  case IFSTATE_ELSE_FALSE:
3912  if (command->meta == META_IF)
3914  IFSTATE_IGNORED);
3915  else if (command->meta == META_ENDIF)
3916  {
3919  if (conditional_active(st->cstack))
3921  }
3922  /* could detect "else" & "elif" after "else" */
3923  st->command++;
3924  break;
3925 
3926  case IFSTATE_NONE:
3927  case IFSTATE_TRUE:
3928  case IFSTATE_ELSE_TRUE:
3929  default:
3930 
3931  /*
3932  * inconsistent if inactive, unreachable dead
3933  * code
3934  */
3935  Assert(false);
3936  }
3937  }
3938  else
3939  {
3940  /* skip and consider next */
3941  st->command++;
3942  }
3943 
3944  if (st->state != CSTATE_SKIP_COMMAND)
3945  /* out of quick skip command loop */
3946  break;
3947  }
3948  break;
3949 
3950  /*
3951  * Wait for the current SQL command to complete
3952  */
3953  case CSTATE_WAIT_RESULT:
3954  pg_log_debug("client %d receiving", st->id);
3955 
3956  /*
3957  * Only check for new network data if we processed all data
3958  * fetched prior. Otherwise we end up doing a syscall for each
3959  * individual pipelined query, which has a measurable
3960  * performance impact.
3961  */
3962  if (PQisBusy(st->con) && !PQconsumeInput(st->con))
3963  {
3964  /* there's something wrong */
3965  commandFailed(st, "SQL", "perhaps the backend died while processing");
3966  st->state = CSTATE_ABORTED;
3967  break;
3968  }
3969  if (PQisBusy(st->con))
3970  return; /* don't have the whole result yet */
3971 
3972  /* store or discard the query results */
3973  if (readCommandResponse(st,
3976  {
3977  /*
3978  * outside of pipeline mode: stop reading results.
3979  * pipeline mode: continue reading results until an
3980  * end-of-pipeline response.
3981  */
3982  if (PQpipelineStatus(st->con) != PQ_PIPELINE_ON)
3983  st->state = CSTATE_END_COMMAND;
3984  }
3985  else if (canRetryError(st->estatus))
3986  st->state = CSTATE_ERROR;
3987  else
3988  st->state = CSTATE_ABORTED;
3989  break;
3990 
3991  /*
3992  * Wait until sleep is done. This state is entered after a
3993  * \sleep metacommand. The behavior is similar to
3994  * CSTATE_THROTTLE, but proceeds to CSTATE_START_COMMAND
3995  * instead of CSTATE_START_TX.
3996  */
3997  case CSTATE_SLEEP:
3999  if (now < st->sleep_until)
4000  return; /* still sleeping, nothing to do here */
4001  /* Else done sleeping. */
4002  st->state = CSTATE_END_COMMAND;
4003  break;
4004 
4005  /*
4006  * End of command: record stats and proceed to next command.
4007  */
4008  case CSTATE_END_COMMAND:
4009 
4010  /*
4011  * command completed: accumulate per-command execution times
4012  * in thread-local data structure, if per-command latencies
4013  * are requested.
4014  */
4015  if (report_per_command)
4016  {
4018 
4019  command = sql_script[st->use_file].commands[st->command];
4020  /* XXX could use a mutex here, but we choose not to */
4021  addToSimpleStats(&command->stats,
4023  }
4024 
4025  /* Go ahead with next command, to be executed or skipped */
4026  st->command++;
4027  st->state = conditional_active(st->cstack) ?
4029  break;
4030 
4031  /*
4032  * Clean up after an error.
4033  */
4034  case CSTATE_ERROR:
4035  {
4036  TStatus tstatus;
4037 
4039 
4040  /* Clear the conditional stack */
4042 
4043  /* Read and discard until a sync point in pipeline mode */
4044  if (PQpipelineStatus(st->con) != PQ_PIPELINE_OFF)
4045  {
4046  if (!discardUntilSync(st))
4047  {
4048  st->state = CSTATE_ABORTED;
4049  break;
4050  }
4051  }
4052 
4053  /*
4054  * Check if we have a (failed) transaction block or not,
4055  * and roll it back if any.
4056  */
4057  tstatus = getTransactionStatus(st->con);
4058  if (tstatus == TSTATUS_IN_BLOCK)
4059  {
4060  /* Try to rollback a (failed) transaction block. */
4061  if (!PQsendQuery(st->con, "ROLLBACK"))
4062  {
4063  pg_log_error("client %d aborted: failed to send sql command for rolling back the failed transaction",
4064  st->id);
4065  st->state = CSTATE_ABORTED;
4066  }
4067  else
4069  }
4070  else if (tstatus == TSTATUS_IDLE)
4071  {
4072  /*
4073  * If time is over, we're done; otherwise, check if we
4074  * can retry the error.
4075  */
4078  }
4079  else
4080  {
4081  if (tstatus == TSTATUS_CONN_ERROR)
4082  pg_log_error("perhaps the backend died while processing");
4083 
4084  pg_log_error("client %d aborted while receiving the transaction status", st->id);
4085  st->state = CSTATE_ABORTED;
4086  }
4087  break;
4088  }
4089 
4090  /*
4091  * Wait for the rollback command to complete
4092  */
4094  {
4095  PGresult *res;
4096 
4097  pg_log_debug("client %d receiving", st->id);
4098  if (!PQconsumeInput(st->con))
4099  {
4100  pg_log_error("client %d aborted while rolling back the transaction after an error; perhaps the backend died while processing",
4101  st->id);
4102  st->state = CSTATE_ABORTED;
4103  break;
4104  }
4105  if (PQisBusy(st->con))
4106  return; /* don't have the whole result yet */
4107 
4108  /*
4109  * Read and discard the query result;
4110  */
4111  res = PQgetResult(st->con);
4112  switch (PQresultStatus(res))
4113  {
4114  case PGRES_COMMAND_OK:
4115  /* OK */
4116  PQclear(res);
4117  /* null must be returned */
4118  res = PQgetResult(st->con);
4119  Assert(res == NULL);
4120 
4121  /*
4122  * If time is over, we're done; otherwise, check
4123  * if we can retry the error.
4124  */
4127  break;
4128  default:
4129  pg_log_error("client %d aborted while rolling back the transaction after an error; %s",
4130  st->id, PQerrorMessage(st->con));
4131  PQclear(res);
4132  st->state = CSTATE_ABORTED;
4133  break;
4134  }
4135  break;
4136  }
4137 
4138  /*
4139  * Retry the transaction after an error.
4140  */
4141  case CSTATE_RETRY:
4142  command = sql_script[st->use_file].commands[st->command];
4143 
4144  /*
4145  * Inform that the transaction will be retried after the
4146  * error.
4147  */
4148  if (verbose_errors)
4149  printVerboseErrorMessages(st, &now, true);
4150 
4151  /* Count tries and retries */
4152  st->tries++;
4153  command->retries++;
4154 
4155  /*
4156  * Reset the random state as they were at the beginning of the
4157  * transaction.
4158  */
4159  st->cs_func_rs = st->random_state;
4160 
4161  /* Process the first transaction command. */
4162  st->command = 0;
4163  st->estatus = ESTATUS_NO_ERROR;
4165  break;
4166 
4167  /*
4168  * Record a failed transaction.
4169  */
4170  case CSTATE_FAILURE:
4171  command = sql_script[st->use_file].commands[st->command];
4172 
4173  /* Accumulate the failure. */
4174  command->failures++;
4175 
4176  /*
4177  * Inform that the failed transaction will not be retried.
4178  */
4179  if (verbose_errors)
4180  printVerboseErrorMessages(st, &now, false);
4181 
4182  /* End the failed transaction. */
4183  st->state = CSTATE_END_TX;
4184  break;
4185 
4186  /*
4187  * End of transaction (end of script, really).
4188  */
4189  case CSTATE_END_TX:
4190  {
4191  TStatus tstatus;
4192 
4193  /* transaction finished: calculate latency and do log */
4194  processXactStats(thread, st, &now, false, agg);
4195 
4196  /*
4197  * missing \endif... cannot happen if CheckConditional was
4198  * okay
4199  */
4201 
4202  /*
4203  * We must complete all the transaction blocks that were
4204  * started in this script.
4205  */
4206  tstatus = getTransactionStatus(st->con);
4207  if (tstatus == TSTATUS_IN_BLOCK)
4208  {
4209  pg_log_error("client %d aborted: end of script reached without completing the last transaction",
4210  st->id);
4211  st->state = CSTATE_ABORTED;
4212  break;
4213  }
4214  else if (tstatus != TSTATUS_IDLE)
4215  {
4216  if (tstatus == TSTATUS_CONN_ERROR)
4217  pg_log_error("perhaps the backend died while processing");
4218 
4219  pg_log_error("client %d aborted while receiving the transaction status", st->id);
4220  st->state = CSTATE_ABORTED;
4221  break;
4222  }
4223 
4224  if (is_connect)
4225  {
4226  pg_time_usec_t start = now;
4227 
4228  pg_time_now_lazy(&start);
4229  finishCon(st);
4230  now = pg_time_now();
4231  thread->conn_duration += now - start;
4232  }
4233 
4234  if ((st->cnt >= nxacts && duration <= 0) || timer_exceeded)
4235  {
4236  /* script completed */
4237  st->state = CSTATE_FINISHED;
4238  break;
4239  }
4240 
4241  /* next transaction (script) */
4243 
4244  /*
4245  * Ensure that we always return on this point, so as to
4246  * avoid an infinite loop if the script only contains meta
4247  * commands.
4248  */
4249  return;
4250  }
4251 
4252  /*
4253  * Final states. Close the connection if it's still open.
4254  */
4255  case CSTATE_ABORTED:
4256  case CSTATE_FINISHED:
4257 
4258  /*
4259  * Don't measure the disconnection delays here even if in
4260  * CSTATE_FINISHED and -C/--connect option is specified.
4261  * Because in this case all the connections that this thread
4262  * established are closed at the end of transactions and the
4263  * disconnection delays should have already been measured at
4264  * that moment.
4265  *
4266  * In CSTATE_ABORTED state, the measurement is no longer
4267  * necessary because we cannot report complete results anyways
4268  * in this case.
4269  */
4270  finishCon(st);
4271  return;
4272  }
4273  }
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1619
ifState conditional_stack_peek(ConditionalStack cstack)
Definition: conditional.c:106
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:53
bool conditional_stack_pop(ConditionalStack cstack)
Definition: conditional.c:69
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
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6841
PGpipelineStatus PQpipelineStatus(const PGconn *conn)
Definition: fe-connect.c:6883
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3371
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1960
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1425
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2007
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2038
void pg_free(void *ptr)
Definition: fe_memutils.c:105
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:158
@ PQ_PIPELINE_ON
Definition: libpq-fe.h:159
Assert(fmt[strlen(fmt) - 1] !='\n')
#define pg_log_debug(...)
Definition: logging.h:133
static pg_time_usec_t pg_time_now(void)
Definition: pgbench.c:850
static void printVerboseErrorMessages(CState *st, pg_time_usec_t *now, bool is_retry)
Definition: pgbench.c:3549
int64 latency_limit
Definition: pgbench.c:211
static TStatus getTransactionStatus(PGconn *con)
Definition: pgbench.c:3512
int64 end_time
Definition: pgbench.c:175
static bool doRetry(CState *st, pg_time_usec_t *now)
Definition: pgbench.c:3426
static bool sendCommand(CState *st, Command *command)
Definition: pgbench.c:3153
TStatus
Definition: pgbench.c:468
static void finishCon(CState *st)
Definition: pgbench.c:7686
int64 pg_time_usec_t
Definition: pgbench.c:369
bool is_connect
Definition: pgbench.c:265
int nxacts
Definition: pgbench.c:173
bool report_per_command
Definition: pgbench.c:266
#define PG_TIME_GET_DOUBLE(t)
Definition: pgbench.c:866
static int discardUntilSync(CState *st)
Definition: pgbench.c:3472
static ConnectionStateEnum executeMetaCommand(CState *st, pg_time_usec_t *now)
Definition: pgbench.c:4283
static bool canRetryError(EStatus estatus)
Definition: pgbench.c:3223
static void commandFailed(CState *st, const char *cmd, const char *message)
Definition: pgbench.c:3026
static int chooseScript(TState *thread)
Definition: pgbench.c:3045
#define SQL_COMMAND
Definition: pgbench.c:677
volatile sig_atomic_t timer_exceeded
Definition: pgbench.c:303
static void processXactStats(TState *thread, CState *st, pg_time_usec_t *now, bool skipped, StatsData *agg)
Definition: pgbench.c:4664
int duration
Definition: pgbench.c:174
static void pg_time_now_lazy(pg_time_usec_t *now)
Definition: pgbench.c:860
static bool verbose_errors
Definition: pgbench.c:767
static int64 getPoissonRand(pg_prng_state *state, double center)
Definition: pgbench.c:1177
static PGconn * doConnect(void)
Definition: pgbench.c:1529
#define META_COMMAND
Definition: pgbench.c:678
static bool readCommandResponse(CState *st, MetaCommand meta, char *varprefix)
Definition: pgbench.c:3239
int64 cnt
Definition: pgbench.c:636
int id
Definition: pgbench.c:598
pg_time_usec_t txn_scheduled
Definition: pgbench.c:616
pg_time_usec_t stmt_begin
Definition: pgbench.c:619
int command
Definition: pgbench.c:609
int use_file
Definition: pgbench.c:608
ConditionalStack cstack
Definition: pgbench.c:600
pg_prng_state random_state
Definition: pgbench.c:631
pg_time_usec_t txn_begin
Definition: pgbench.c:618
EStatus estatus
Definition: pgbench.c:628
PGconn * con
Definition: pgbench.c:597
pg_prng_state cs_func_rs
Definition: pgbench.c:606
uint32 tries
Definition: pgbench.c:632
bool ** prepared
Definition: pgbench.c:622
ConnectionStateEnum state
Definition: pgbench.c:599
int64 retries
Definition: pgbench.c:751
char * varprefix
Definition: pgbench.c:748
int type
Definition: pgbench.c:743
MetaCommand meta
Definition: pgbench.c:744
SimpleStats stats
Definition: pgbench.c:750
int64 failures
Definition: pgbench.c:752
int64 throttle_trigger
Definition: pgbench.c:660
pg_prng_state ts_throttle_rs
Definition: pgbench.c:657
pg_time_usec_t conn_duration
Definition: pgbench.c:667

References addToSimpleStats(), Assert(), canRetryError(), chooseScript(), CState::cnt, CState::command, commandFailed(), ParsedScript::commands, CState::con, conditional_active(), conditional_stack_empty(), conditional_stack_peek(), conditional_stack_poke(), conditional_stack_pop(), conditional_stack_push(), conditional_stack_reset(), TState::conn_duration, CState::cs_func_rs, CState::cstack, CSTATE_ABORTED, CSTATE_CHOOSE_SCRIPT, CSTATE_END_COMMAND, CSTATE_END_TX, CSTATE_ERROR, CSTATE_FAILURE, CSTATE_FINISHED, CSTATE_PREPARE_THROTTLE, CSTATE_RETRY, CSTATE_SKIP_COMMAND, CSTATE_SLEEP, CSTATE_START_COMMAND, CSTATE_START_TX, CSTATE_THROTTLE, CSTATE_WAIT_RESULT, CSTATE_WAIT_ROLLBACK_RESULT, ParsedScript::desc, discardUntilSync(), doConnect(), doRetry(), duration, end_time, CState::estatus, ESTATUS_META_COMMAND_ERROR, ESTATUS_NO_ERROR, executeMetaCommand(), Command::failures, finishCon(), getPoissonRand(), getTransactionStatus(), CState::id, IFSTATE_ELSE_FALSE, IFSTATE_ELSE_TRUE, IFSTATE_FALSE, IFSTATE_IGNORED, IFSTATE_NONE, IFSTATE_TRUE, is_connect, latency_limit, Command::meta, META_ASET, META_COMMAND, META_ELIF, META_ELSE, META_ENDIF, META_GSET, META_IF, now(), nxacts, pg_free(), pg_log_debug, pg_log_error, PG_TIME_GET_DOUBLE, pg_time_now(), pg_time_now_lazy(), PGRES_COMMAND_OK, PQ_PIPELINE_OFF, PQ_PIPELINE_ON, PQclear(), PQconsumeInput(), PQerrorMessage(), PQgetResult(), PQisBusy(), PQpipelineStatus(), PQresultStatus(), PQsendQuery(), CState::prepared, printVerboseErrorMessages(), processXactStats(), CState::random_state, readCommandResponse(), report_per_command, res, Command::retries, sendCommand(), SQL_COMMAND, sql_script, CState::state, Command::stats, CState::stmt_begin, throttle_delay, TState::throttle_trigger, timer_exceeded, CState::tries, TState::ts_throttle_rs, TSTATUS_CONN_ERROR, TSTATUS_IDLE, TSTATUS_IN_BLOCK, CState::txn_begin, CState::txn_scheduled, Command::type, CState::use_file, Command::varprefix, and verbose_errors.

Referenced by threadRun().

◆ alloc_socket_set()

static socket_set * alloc_socket_set ( int  count)
static

Definition at line 7851 of file pgbench.c.

7853 {
7854  return (socket_set *) pg_malloc0(sizeof(socket_set));
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53

References pg_malloc0().

Referenced by threadRun().

◆ allocCStatePrepared()

static void allocCStatePrepared ( CState st)
static

Definition at line 3067 of file pgbench.c.

3069 {
3070  Assert(st->prepared == NULL);
3071 
3072  st->prepared = pg_malloc(sizeof(bool *) * num_scripts);
3073  for (int i = 0; i < num_scripts; i++)
3074  {
3075  ParsedScript *script = &sql_script[i];
3076  int numcmds;
3077 
3078  for (numcmds = 0; script->commands[numcmds] != NULL; numcmds++)
3079  ;
3080  st->prepared[i] = pg_malloc0(sizeof(bool) * numcmds);
3081  }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
int i
Definition: isn.c:73

References Assert(), ParsedScript::commands, i, num_scripts, pg_malloc(), pg_malloc0(), CState::prepared, and sql_script.

Referenced by prepareCommand(), and prepareCommandsInPipeline().

◆ assignVariables()

static char* assignVariables ( Variables variables,
char *  sql 
)
static

Definition at line 1934 of file pgbench.c.

1936 {
1937  char *p,
1938  *name,
1939  *val;
1940 
1941  p = sql;
1942  while ((p = strchr(p, ':')) != NULL)
1943  {
1944  int eaten;
1945 
1946  name = parseVariable(p, &eaten);
1947  if (name == NULL)
1948  {
1949  while (*p == ':')
1950  {
1951  p++;
1952  }
1953  continue;
1954  }
1955 
1956  val = getVariable(variables, name);
1957  free(name);
1958  if (val == NULL)
1959  {
1960  p++;
1961  continue;
1962  }
1963 
1964  p = replaceVariable(&sql, p, eaten, val);
1965  }
1966 
1967  return sql;
#define free(a)
Definition: header.h:65
static char * getVariable(Variables *variables, char *name)
Definition: pgbench.c:1629
static char * parseVariable(const char *sql, int *eaten)
Definition: pgbench.c:1887
static char * replaceVariable(char **sql, char *param, int len, char *value)
Definition: pgbench.c:1914
const char * name

References free, getVariable(), name, parseVariable(), replaceVariable(), and val.

Referenced by sendCommand().

◆ canRetryError()

static bool canRetryError ( EStatus  estatus)
static

Definition at line 3223 of file pgbench.c.

3225 {
3226  return (estatus == ESTATUS_SERIALIZATION_ERROR ||
3227  estatus == ESTATUS_DEADLOCK_ERROR);

References ESTATUS_DEADLOCK_ERROR, and ESTATUS_SERIALIZATION_ERROR.

Referenced by advanceConnectionState(), doRetry(), and readCommandResponse().

◆ CheckConditional()

static void CheckConditional ( const ParsedScript ps)
static

Definition at line 5853 of file pgbench.c.

5855 {
5856  /* statically check conditional structure */
5858  int i;
5859 
5860  for (i = 0; ps->commands[i] != NULL; i++)
5861  {
5862  Command *cmd = ps->commands[i];
5863 
5864  if (cmd->type == META_COMMAND)
5865  {
5866  switch (cmd->meta)
5867  {
5868  case META_IF:
5870  break;
5871  case META_ELIF:
5872  if (conditional_stack_empty(cs))
5873  ConditionError(ps->desc, i + 1, "\\elif without matching \\if");
5875  ConditionError(ps->desc, i + 1, "\\elif after \\else");
5876  break;
5877  case META_ELSE:
5878  if (conditional_stack_empty(cs))
5879  ConditionError(ps->desc, i + 1, "\\else without matching \\if");
5881  ConditionError(ps->desc, i + 1, "\\else after \\else");
5883  break;
5884  case META_ENDIF:
5885  if (!conditional_stack_pop(cs))
5886  ConditionError(ps->desc, i + 1, "\\endif without matching \\if");
5887  break;
5888  default:
5889  /* ignore anything else... */
5890  break;
5891  }
5892  }
5893  }
5894  if (!conditional_stack_empty(cs))
5895  ConditionError(ps->desc, i + 1, "\\if without matching \\endif");
ConditionalStack conditional_stack_create(void)
Definition: conditional.c:18
void conditional_stack_destroy(ConditionalStack cstack)
Definition: conditional.c:43
struct parser_state ps
static void ConditionError(const char *desc, int cmdn, const char *msg)
Definition: pgbench.c:5843

References conditional_stack_create(), conditional_stack_destroy(), conditional_stack_empty(), conditional_stack_peek(), conditional_stack_poke(), conditional_stack_pop(), conditional_stack_push(), ConditionError(), i, IFSTATE_ELSE_FALSE, IFSTATE_FALSE, Command::meta, META_COMMAND, META_ELIF, META_ELSE, META_ENDIF, META_IF, ps, and Command::type.

Referenced by addScript().

◆ checkInitSteps()

static void checkInitSteps ( const char *  initialize_steps)
static

Definition at line 5201 of file pgbench.c.

5203 {
5204  if (initialize_steps[0] == '\0')
5205  pg_fatal("no initialization steps specified");
5206 
5207  for (const char *step = initialize_steps; *step != '\0'; step++)
5208  {
5209  if (strchr(ALL_INIT_STEPS " ", *step) == NULL)
5210  {
5211  pg_log_error("unrecognized initialization step \"%c\"", *step);
5212  pg_log_error_detail("Allowed step characters are: \"" ALL_INIT_STEPS "\".");
5213  exit(1);
5214  }
5215  }
#define pg_log_error_detail(...)
Definition: logging.h:109
#define ALL_INIT_STEPS
Definition: pgbench.c:163

References ALL_INIT_STEPS, exit(), pg_fatal, pg_log_error, and pg_log_error_detail.

Referenced by main().

◆ chooseScript()

static int chooseScript ( TState thread)
static

Definition at line 3045 of file pgbench.c.

3047 {
3048  int i = 0;
3049  int64 w;
3050 
3051  if (num_scripts == 1)
3052  return 0;
3053 
3054  w = getrand(&thread->ts_choose_rs, 0, total_weight - 1);
3055  do
3056  {
3057  w -= sql_script[i++].weight;
3058  } while (w >= 0);
3059 
3060  return i - 1;
static int64 total_weight
Definition: pgbench.c:765
static int64 getrand(pg_prng_state *state, int64 min, int64 max)
Definition: pgbench.c:1100
int weight
Definition: pgbench.c:758
pg_prng_state ts_choose_rs
Definition: pgbench.c:656

References getrand(), i, num_scripts, sql_script, total_weight, TState::ts_choose_rs, and ParsedScript::weight.

Referenced by advanceConnectionState().

◆ clear_socket_set()

static void clear_socket_set ( socket_set sa)
static

Definition at line 7863 of file pgbench.c.

7865 {
7866  FD_ZERO(&sa->fds);
7867  sa->maxfd = -1;

Referenced by threadRun().

◆ coerceToBool()

static bool coerceToBool ( PgBenchValue pval,
bool bval 
)
static

Definition at line 2002 of file pgbench.c.

2004 {
2005  if (pval->type == PGBT_BOOLEAN)
2006  {
2007  *bval = pval->u.bval;
2008  return true;
2009  }
2010  else /* NULL, INT or DOUBLE */
2011  {
2012  pg_log_error("cannot coerce %s to boolean", valueTypeName(pval));
2013  *bval = false; /* suppress uninitialized-variable warnings */
2014  return false;
2015  }
static char * valueTypeName(PgBenchValue *pval)
Definition: pgbench.c:1980
@ PGBT_BOOLEAN
Definition: pgbench.h:40
PgBenchValueType type
Definition: pgbench.h:46
bool bval
Definition: pgbench.h:51
union PgBenchValue::@33 u

References PgBenchValue::bval, pg_log_error, PGBT_BOOLEAN, PgBenchValue::type, PgBenchValue::u, and valueTypeName().

Referenced by evalLazyFunc(), and evalStandardFunc().

◆ coerceToDouble()

static bool coerceToDouble ( PgBenchValue pval,
double *  dval 
)
static

Definition at line 2071 of file pgbench.c.

2073 {
2074  if (pval->type == PGBT_DOUBLE)
2075  {
2076  *dval = pval->u.dval;
2077  return true;
2078  }
2079  else if (pval->type == PGBT_INT)
2080  {
2081  *dval = (double) pval->u.ival;
2082  return true;
2083  }
2084  else /* BOOLEAN or NULL */
2085  {
2086  pg_log_error("cannot coerce %s to double", valueTypeName(pval));
2087  return false;
2088  }
@ PGBT_INT
Definition: pgbench.h:38
@ PGBT_DOUBLE
Definition: pgbench.h:39
int64 ival
Definition: pgbench.h:49
double dval
Definition: pgbench.h:50

References PgBenchValue::dval, PgBenchValue::ival, pg_log_error, PGBT_DOUBLE, PGBT_INT, PgBenchValue::type, PgBenchValue::u, and valueTypeName().

Referenced by evalStandardFunc().

◆ coerceToInt()

static bool coerceToInt ( PgBenchValue pval,
int64 *  ival 
)
static

Definition at line 2043 of file pgbench.c.

2045 {
2046  if (pval->type == PGBT_INT)
2047  {
2048  *ival = pval->u.ival;
2049  return true;
2050  }
2051  else if (pval->type == PGBT_DOUBLE)
2052  {
2053  double dval = rint(pval->u.dval);
2054 
2055  if (isnan(dval) || !FLOAT8_FITS_IN_INT64(dval))
2056  {
2057  pg_log_error("double to int overflow for %f", dval);
2058  return false;
2059  }
2060  *ival = (int64) dval;
2061  return true;
2062  }
2063  else /* BOOLEAN or NULL */
2064  {
2065  pg_log_error("cannot coerce %s to int", valueTypeName(pval));
2066  return false;
2067  }
#define FLOAT8_FITS_IN_INT64(num)
Definition: c.h:1081

References PgBenchValue::dval, FLOAT8_FITS_IN_INT64, PgBenchValue::ival, pg_log_error, PGBT_DOUBLE, PGBT_INT, PgBenchValue::type, PgBenchValue::u, and valueTypeName().

Referenced by evalStandardFunc().

◆ commandError()

static void commandError ( CState st,
const char *  message 
)
static

Definition at line 3036 of file pgbench.c.

3038 {
3040  pg_log_info("client %d got an error in command %d (SQL) of script %d; %s",
3041  st->id, st->command, st->use_file, message);
#define pg_log_info(...)
Definition: logging.h:124

References Assert(), CState::command, ParsedScript::commands, CState::id, pg_log_info, SQL_COMMAND, sql_script, Command::type, and CState::use_file.

Referenced by readCommandResponse().

◆ commandFailed()

static void commandFailed ( CState st,
const char *  cmd,
const char *  message 
)
static

Definition at line 3026 of file pgbench.c.

3028 {
3029  pg_log_error("client %d aborted in command %d (%s) of script %d; %s",
3030  st->id, st->command, cmd, st->use_file, message);

References CState::command, CState::id, pg_log_error, and CState::use_file.

Referenced by advanceConnectionState(), and executeMetaCommand().

◆ compareVariableNames()

static int compareVariableNames ( const void *  v1,
const void *  v2 
)
static

Definition at line 1594 of file pgbench.c.

1596 {
1597  return strcmp(((const Variable *) v1)->name,
1598  ((const Variable *) v2)->name);

References name.

Referenced by lookupVariable().

◆ computeIterativeZipfian()

static int64 computeIterativeZipfian ( pg_prng_state state,
int64  n,
double  s 
)
static

Definition at line 1199 of file pgbench.c.

1201 {
1202  double b = pow(2.0, s - 1.0);
1203  double x,
1204  t,
1205  u,
1206  v;
1207 
1208  /* Ensure n is sane */
1209  if (n <= 1)
1210  return 1;
1211 
1212  while (true)
1213  {
1214  /* random variates */
1215  u = pg_prng_double(state);
1216  v = pg_prng_double(state);
1217 
1218  x = floor(pow(u, -1.0 / (s - 1.0)));
1219 
1220  t = pow(1.0 + 1.0 / x, s - 1.0);
1221  /* reject if too large or out of bound */
1222  if (v * x * (t - 1.0) / (b - 1.0) <= t / b && x <= n)
1223  break;
1224  }
1225  return (int64) x;
int b
Definition: isn.c:70
int x
Definition: isn.c:71
double pg_prng_double(pg_prng_state *state)
Definition: pg_prng.c:232
Definition: regguts.h:323

References b, pg_prng_double(), and x.

Referenced by getZipfianRand().

◆ ConditionError()

static void ConditionError ( const char *  desc,
int  cmdn,
const char *  msg 
)
static

Definition at line 5843 of file pgbench.c.

5845 {
5846  pg_fatal("condition error in script \"%s\" command %d: %s",
5847  desc, cmdn, msg);

References pg_fatal.

Referenced by CheckConditional().

◆ create_sql_command()

static Command* create_sql_command ( PQExpBuffer  buf,
const char *  source 
)
static

Definition at line 5547 of file pgbench.c.

5549 {
5550  Command *my_command;
5551  char *p = skip_sql_comments(buf->data);
5552 
5553  if (p == NULL)
5554  return NULL;
5555 
5556  /* Allocate and initialize Command structure */
5557  my_command = (Command *) pg_malloc(sizeof(Command));
5558  initPQExpBuffer(&my_command->lines);
5559  appendPQExpBufferStr(&my_command->lines, p);
5560  my_command->first_line = NULL; /* this is set later */
5561  my_command->type = SQL_COMMAND;
5562  my_command->meta = META_NONE;
5563  my_command->argc = 0;
5564  my_command->retries = 0;
5565  my_command->failures = 0;
5566  memset(my_command->argv, 0, sizeof(my_command->argv));
5567  my_command->varprefix = NULL; /* allocated later, if needed */
5568  my_command->expr = NULL;
5569  initSimpleStats(&my_command->stats);
5570  my_command->prepname = NULL; /* set later, if needed */
5571 
5572  return my_command;
static char * buf
Definition: pg_test_fsync.c:73
static char * skip_sql_comments(char *sql_command)
Definition: pgbench.c:5512
static void initSimpleStats(SimpleStats *ss)
Definition: pgbench.c:1392
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
PQExpBufferData lines
Definition: pgbench.c:741
PgBenchExpr * expr
Definition: pgbench.c:749
char * argv[MAX_ARGS]
Definition: pgbench.c:746
char * first_line
Definition: pgbench.c:742
int argc
Definition: pgbench.c:745
char * prepname
Definition: pgbench.c:747

References appendPQExpBufferStr(), Command::argc, Command::argv, buf, Command::expr, Command::failures, Command::first_line, initPQExpBuffer(), initSimpleStats(), Command::lines, Command::meta, META_NONE, pg_malloc(), Command::prepname, Command::retries, skip_sql_comments(), SQL_COMMAND, Command::stats, Command::type, and Command::varprefix.

Referenced by ParseScript().

◆ createPartitions()

static void createPartitions ( PGconn con)
static

Definition at line 4737 of file pgbench.c.

4739 {
4740  PQExpBufferData query;
4741 
4742  /* we must have to create some partitions */
4743  Assert(partitions > 0);
4744 
4745  fprintf(stderr, "creating %d partitions...\n", partitions);
4746 
4747  initPQExpBuffer(&query);
4748 
4749  for (int p = 1; p <= partitions; p++)
4750  {
4752  {
4753  int64 part_size = (naccounts * (int64) scale + partitions - 1) / partitions;
4754 
4755  printfPQExpBuffer(&query,
4756  "create%s table pgbench_accounts_%d\n"
4757  " partition of pgbench_accounts\n"
4758  " for values from (",
4759  unlogged_tables ? " unlogged" : "", p);
4760 
4761  /*
4762  * For RANGE, we use open-ended partitions at the beginning and
4763  * end to allow any valid value for the primary key. Although the
4764  * actual minimum and maximum values can be derived from the
4765  * scale, it is more generic and the performance is better.
4766  */
4767  if (p == 1)
4768  appendPQExpBufferStr(&query, "minvalue");
4769  else
4770  appendPQExpBuffer(&query, INT64_FORMAT, (p - 1) * part_size + 1);
4771 
4772  appendPQExpBufferStr(&query, ") to (");
4773 
4774  if (p < partitions)
4775  appendPQExpBuffer(&query, INT64_FORMAT, p * part_size + 1);
4776  else
4777  appendPQExpBufferStr(&query, "maxvalue");
4778 
4779  appendPQExpBufferChar(&query, ')');
4780  }
4781  else if (partition_method == PART_HASH)
4782  printfPQExpBuffer(&query,
4783  "create%s table pgbench_accounts_%d\n"
4784  " partition of pgbench_accounts\n"
4785  " for values with (modulus %d, remainder %d)",
4786  unlogged_tables ? " unlogged" : "", p,
4787  partitions, p - 1);
4788  else /* cannot get there */
4789  Assert(0);
4790 
4791  /*
4792  * Per ddlinfo in initCreateTables, fillfactor is needed on table
4793  * pgbench_accounts.
4794  */
4795  appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
4796 
4797  executeStatement(con, query.data);
4798  }
4799 
4800  termPQExpBuffer(&query);
#define INT64_FORMAT
Definition: c.h:537
int scale
Definition: pgbench.c:181
static int partitions
Definition: pgbench.c:223
int fillfactor
Definition: pgbench.c:187
static partition_method_t partition_method
Definition: pgbench.c:233
bool unlogged_tables
Definition: pgbench.c:192
#define naccounts
Definition: pgbench.c:245
static void executeStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1498
#define fprintf
Definition: port.h:242
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:235
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), Assert(), PQExpBufferData::data, executeStatement(), fillfactor, fprintf, initPQExpBuffer(), INT64_FORMAT, naccounts, PART_HASH, PART_RANGE, partition_method, partitions, printfPQExpBuffer(), scale, termPQExpBuffer(), and unlogged_tables.

Referenced by initCreateTables().

◆ discardUntilSync()

static int discardUntilSync ( CState st)
static

Definition at line 3472 of file pgbench.c.

3474 {
3475  /* send a sync */
3476  if (!PQpipelineSync(st->con))
3477  {
3478  pg_log_error("client %d aborted: failed to send a pipeline sync",
3479  st->id);
3480  return 0;
3481  }
3482 
3483  /* receive PGRES_PIPELINE_SYNC and null following it */
3484  for (;;)
3485  {
3486  PGresult *res = PQgetResult(st->con);
3487 
3489  {
3490  PQclear(res);
3491  res = PQgetResult(st->con);
3492  Assert(res == NULL);
3493  break;
3494  }
3495  PQclear(res);
3496  }
3497 
3498  /* exit pipeline */
3499  if (PQexitPipelineMode(st->con) != 1)
3500  {
3501  pg_log_error("client %d aborted: failed to exit pipeline mode for rolling back the failed transaction",
3502  st->id);
3503  return 0;
3504  }
3505  return 1;
int PQexitPipelineMode(PGconn *conn)
Definition: fe-exec.c:3035
int PQpipelineSync(PGconn *conn)
Definition: fe-exec.c:3232
@ PGRES_PIPELINE_SYNC
Definition: libpq-fe.h:111

References Assert(), CState::con, CState::id, pg_log_error, PGRES_PIPELINE_SYNC, PQclear(), PQexitPipelineMode(), PQgetResult(), PQpipelineSync(), PQresultStatus(), and res.

Referenced by advanceConnectionState().

◆ disconnect_all()

static void disconnect_all ( CState state,
int  length 
)
static

Definition at line 4703 of file pgbench.c.

4705 {
4706  int i;
4707 
4708  for (i = 0; i < length; i++)
4709  finishCon(&state[i]);

References finishCon(), and i.

Referenced by main(), and threadRun().

◆ doConnect()

static PGconn* doConnect ( void  )
static

Definition at line 1529 of file pgbench.c.

1531 {
1532  PGconn *conn;
1533  bool new_pass;
1534  static char *password = NULL;
1535 
1536  /*
1537  * Start the connection. Loop until we have a password if requested by
1538  * backend.
1539  */
1540  do
1541  {
1542 #define PARAMS_ARRAY_SIZE 7
1543 
1544  const char *keywords[PARAMS_ARRAY_SIZE];
1545  const char *values[PARAMS_ARRAY_SIZE];
1546 
1547  keywords[0] = "host";
1548  values[0] = pghost;
1549  keywords[1] = "port";
1550  values[1] = pgport;
1551  keywords[2] = "user";
1552  values[2] = username;
1553  keywords[3] = "password";
1554  values[3] = password;
1555  keywords[4] = "dbname";
1556  values[4] = dbName;
1557  keywords[5] = "fallback_application_name";
1558  values[5] = progname;
1559  keywords[6] = NULL;
1560  values[6] = NULL;
1561 
1562  new_pass = false;
1563 
1564  conn = PQconnectdbParams(keywords, values, true);
1565 
1566  if (!conn)
1567  {
1568  pg_log_error("connection to database \"%s\" failed", dbName);
1569  return NULL;
1570  }
1571 
1572  if (PQstatus(conn) == CONNECTION_BAD &&
1574  !password)
1575  {
1576  PQfinish(conn);
1577  password = simple_prompt("Password: ", false);
1578  new_pass = true;
1579  }
1580  } while (new_pass);
1581 
1582  /* check to see that the backend connection was successfully made */
1583  if (PQstatus(conn) == CONNECTION_BAD)
1584  {
1586  PQfinish(conn);
1587  return NULL;
1588  }
1589 
1590  return conn;
static Datum values[MAXATTR]
Definition: bootstrap.c:156
PGconn * PQconnectdbParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:669
int PQconnectionNeedsPassword(const PGconn *conn)
Definition: fe-connect.c:6892
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6788
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4562
@ CONNECTION_BAD
Definition: libpq-fe.h:61
#define PARAMS_ARRAY_SIZE
const char * pghost
Definition: pgbench.c:294
const char * username
Definition: pgbench.c:296
const char * progname
Definition: pgbench.c:299
const char * pgport
Definition: pgbench.c:295
const char * dbName
Definition: pgbench.c:297
char * simple_prompt(const char *prompt, bool echo)
Definition: sprompt.c:38
static char * password
Definition: streamutil.c:53
PGconn * conn
Definition: streamutil.c:54

References conn, CONNECTION_BAD, dbName, PARAMS_ARRAY_SIZE, password, pg_log_error, pghost, pgport, PQconnectdbParams(), PQconnectionNeedsPassword(), PQerrorMessage(), PQfinish(), PQstatus(), progname, simple_prompt(), username, and values.

Referenced by advanceConnectionState(), main(), runInitSteps(), and threadRun().

◆ doLog()

static void doLog ( TState thread,
CState st,
StatsData agg,
bool  skipped,
double  latency,
double  lag 
)
static

Definition at line 4544 of file pgbench.c.

4547 {
4548  FILE *logfile = thread->logfile;
4550 
4551  Assert(use_log);
4552 
4553  /*
4554  * Skip the log entry if sampling is enabled and this row doesn't belong
4555  * to the random sample.
4556  */
4557  if (sample_rate != 0.0 &&
4559  return;
4560 
4561  /* should we aggregate the results or not? */
4562  if (agg_interval > 0)
4563  {
4565 
4566  /*
4567  * Loop until we reach the interval of the current moment, and print
4568  * any empty intervals in between (this may happen with very low tps,
4569  * e.g. --rate=0.1).
4570  */
4571 
4572  while ((next = agg->start_time + agg_interval * INT64CONST(1000000)) <= now)
4573  {
4574  double lag_sum = 0.0;
4575  double lag_sum2 = 0.0;
4576  double lag_min = 0.0;
4577  double lag_max = 0.0;
4578  int64 skipped = 0;
4579  int64 serialization_failures = 0;
4580  int64 deadlock_failures = 0;
4581  int64 retried = 0;
4582  int64 retries = 0;
4583 
4584  /* print aggregated report to logfile */
4585  fprintf(logfile, INT64_FORMAT " " INT64_FORMAT " %.0f %.0f %.0f %.0f",
4586  agg->start_time / 1000000, /* seconds since Unix epoch */
4587  agg->cnt,
4588  agg->latency.sum,
4589  agg->latency.sum2,
4590  agg->latency.min,
4591  agg->latency.max);
4592 
4593  if (throttle_delay)
4594  {
4595  lag_sum = agg->lag.sum;
4596  lag_sum2 = agg->lag.sum2;
4597  lag_min = agg->lag.min;
4598  lag_max = agg->lag.max;
4599  }
4600  fprintf(logfile, " %.0f %.0f %.0f %.0f",
4601  lag_sum,
4602  lag_sum2,
4603  lag_min,
4604  lag_max);
4605 
4606  if (latency_limit)
4607  skipped = agg->skipped;
4608  fprintf(logfile, " " INT64_FORMAT, skipped);
4609 
4610  if (max_tries != 1)
4611  {
4612  retried = agg->retried;
4613  retries = agg->retries;
4614  }
4615  fprintf(logfile, " " INT64_FORMAT " " INT64_FORMAT, retried, retries);
4616 
4617  if (failures_detailed)
4618  {
4619  serialization_failures = agg->serialization_failures;
4620  deadlock_failures = agg->deadlock_failures;
4621  }
4623  serialization_failures,
4624  deadlock_failures);
4625 
4626  fputc('\n', logfile);
4627 
4628  /* reset data and move to next interval */
4629  initStats(agg, next);
4630  }
4631 
4632  /* accumulate the current transaction */
4633  accumStats(agg, skipped, latency, lag, st->estatus, st->tries);
4634  }
4635  else
4636  {
4637  /* no, print raw transactions */
4638  if (!skipped && st->estatus == ESTATUS_NO_ERROR)
4639  fprintf(logfile, "%d " INT64_FORMAT " %.0f %d " INT64_FORMAT " "
4640  INT64_FORMAT,
4641  st->id, st->cnt, latency, st->use_file,
4642  now / 1000000, now % 1000000);
4643  else
4644  fprintf(logfile, "%d " INT64_FORMAT " %s %d " INT64_FORMAT " "
4645  INT64_FORMAT,
4646  st->id, st->cnt, getResultString(skipped, st->estatus),
4647  st->use_file, now / 1000000, now % 1000000);
4648 
4649  if (throttle_delay)
4650  fprintf(logfile, " %.0f", lag);
4651  if (max_tries != 1)
4652  fprintf(logfile, " %u", st->tries - 1);
4653  fputc('\n', logfile);
4654  }
static int32 next
Definition: blutils.c:221
static FILE * logfile
Definition: pg_regress.c:127
static void accumStats(StatsData *stats, bool skipped, double lat, double lag, EStatus estatus, int64 tries)
Definition: pgbench.c:1449
uint32 max_tries
Definition: pgbench.c:289
bool use_log
Definition: pgbench.c:256
int agg_interval
Definition: pgbench.c:258
static const char * getResultString(bool skipped, EStatus estatus)
Definition: pgbench.c:4513
static void initStats(StatsData *sd, pg_time_usec_t start)
Definition: pgbench.c:1432
double sample_rate
Definition: pgbench.c:197
bool failures_detailed
Definition: pgbench.c:291
pg_time_usec_t epoch_shift
Definition: pgbench.c:448
pg_time_usec_t start_time
Definition: pgbench.c:377
FILE * logfile
Definition: pgbench.c:661
pg_prng_state ts_sample_rs
Definition: pgbench.c:658

References accumStats(), agg_interval, Assert(), StatsData::cnt, CState::cnt, StatsData::deadlock_failures, epoch_shift, CState::estatus, ESTATUS_NO_ERROR, failures_detailed, fprintf, getResultString(), CState::id, initStats(), INT64_FORMAT, StatsData::lag, StatsData::latency, latency_limit, TState::logfile, logfile, SimpleStats::max, max_tries, SimpleStats::min, next, now(), pg_prng_double(), pg_time_now(), StatsData::retried, StatsData::retries, sample_rate, StatsData::serialization_failures, StatsData::skipped, StatsData::start_time, SimpleStats::sum, SimpleStats::sum2, throttle_delay, CState::tries, TState::ts_sample_rs, CState::use_file, and use_log.

Referenced by processXactStats(), and threadRun().

◆ doRetry()

static bool doRetry ( CState st,
pg_time_usec_t now 
)
static

Definition at line 3426 of file pgbench.c.

3428 {
3430 
3431  /* We can only retry serialization or deadlock errors. */
3432  if (!canRetryError(st->estatus))
3433  return false;
3434 
3435  /*
3436  * We must have at least one option to limit the retrying of transactions
3437  * that got an error.
3438  */
3440 
3441  /*
3442  * We cannot retry the error if we have reached the maximum number of
3443  * tries.
3444  */
3445  if (max_tries && st->tries >= max_tries)
3446  return false;
3447 
3448  /*
3449  * We cannot retry the error if we spent too much time on this
3450  * transaction.
3451  */
3452  if (latency_limit)
3453  {
3455  if (*now - st->txn_scheduled > latency_limit)
3456  return false;
3457  }
3458 
3459  /*
3460  * We cannot retry the error if the benchmark duration is over.
3461  */
3462  if (timer_exceeded)
3463  return false;
3464 
3465  /* OK */
3466  return true;

References Assert(), canRetryError(), duration, CState::estatus, ESTATUS_NO_ERROR, latency_limit, max_tries, now(), pg_time_now_lazy(), timer_exceeded, CState::tries, and CState::txn_scheduled.

Referenced by advanceConnectionState().

◆ enlargeVariables()

static void enlargeVariables ( Variables variables,
int  needed 
)
static

Definition at line 1771 of file pgbench.c.

1773 {
1774  /* total number of variables required now */
1775  needed += variables->nvars;
1776 
1777  if (variables->max_vars < needed)
1778  {
1779  variables->max_vars = needed + VARIABLES_ALLOC_MARGIN;
1780  variables->vars = (Variable *)
1781  pg_realloc(variables->vars, variables->max_vars * sizeof(Variable));
1782  }
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
#define VARIABLES_ALLOC_MARGIN
Definition: pgbench.c:309
Variable * vars
Definition: pgbench.c:333
int nvars
Definition: pgbench.c:334
int max_vars
Definition: pgbench.c:341

References Variables::max_vars, Variables::nvars, pg_realloc(), VARIABLES_ALLOC_MARGIN, and Variables::vars.

Referenced by lookupCreateVariable().

◆ evalFunc()

static bool evalFunc ( CState st,
PgBenchFunction  func,
PgBenchExprLink args,
PgBenchValue retval 
)
static

Definition at line 2819 of file pgbench.c.

2822 {
2823  if (isLazyFunc(func))
2824  return evalLazyFunc(st, func, args, retval);
2825  else
2826  return evalStandardFunc(st, func, args, retval);
static bool isLazyFunc(PgBenchFunction func)
Definition: pgbench.c:2123
static bool evalLazyFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2130
static bool evalStandardFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2247

References generate_unaccent_rules::args, evalLazyFunc(), evalStandardFunc(), and isLazyFunc().

Referenced by evaluateExpr().

◆ evalLazyFunc()

static bool evalLazyFunc ( CState st,
PgBenchFunction  func,
PgBenchExprLink args,
PgBenchValue retval 
)
static

Definition at line 2130 of file pgbench.c.

2133 {
2134  PgBenchValue a1,
2135  a2;
2136  bool ba1,
2137  ba2;
2138 
2139  Assert(isLazyFunc(func) && args != NULL && args->next != NULL);
2140 
2141  /* args points to first condition */
2142  if (!evaluateExpr(st, args->expr, &a1))
2143  return false;
2144 
2145  /* second condition for AND/OR and corresponding branch for CASE */
2146  args = args->next;
2147 
2148  switch (func)
2149  {
2150  case PGBENCH_AND:
2151  if (a1.type == PGBT_NULL)
2152  {
2153  setNullValue(retval);
2154  return true;
2155  }
2156 
2157  if (!coerceToBool(&a1, &ba1))
2158  return false;
2159 
2160  if (!ba1)
2161  {
2162  setBoolValue(retval, false);
2163  return true;
2164  }
2165 
2166  if (!evaluateExpr(st, args->expr, &a2))
2167  return false;
2168 
2169  if (a2.type == PGBT_NULL)
2170  {
2171  setNullValue(retval);
2172  return true;
2173  }
2174  else if (!coerceToBool(&a2, &ba2))
2175  return false;
2176  else
2177  {
2178  setBoolValue(retval, ba2);
2179  return true;
2180  }
2181 
2182  return true;
2183 
2184  case PGBENCH_OR:
2185 
2186  if (a1.type == PGBT_NULL)
2187  {
2188  setNullValue(retval);
2189  return true;
2190  }
2191 
2192  if (!coerceToBool(&a1, &ba1))
2193  return false;
2194 
2195  if (ba1)
2196  {
2197  setBoolValue(retval, true);
2198  return true;
2199  }
2200 
2201  if (!evaluateExpr(st, args->expr, &a2))
2202  return false;
2203 
2204  if (a2.type == PGBT_NULL)
2205  {
2206  setNullValue(retval);
2207  return true;
2208  }
2209  else if (!coerceToBool(&a2, &ba2))
2210  return false;
2211  else
2212  {
2213  setBoolValue(retval, ba2);
2214  return true;
2215  }
2216 
2217  case PGBENCH_CASE:
2218  /* when true, execute branch */
2219  if (valueTruth(&a1))
2220  return evaluateExpr(st, args->expr, retval);
2221 
2222  /* now args contains next condition or final else expression */
2223  args = args->next;
2224 
2225  /* final else case? */
2226  if (args->next == NULL)
2227  return evaluateExpr(st, args->expr, retval);
2228 
2229  /* no, another when, proceed */
2230  return evalLazyFunc(st, PGBENCH_CASE, args, retval);
2231 
2232  default:
2233  /* internal error, cannot get here */
2234  Assert(0);
2235  break;
2236  }
2237  return false;
static const FormData_pg_attribute a1
Definition: heap.c:142
static const FormData_pg_attribute a2
Definition: heap.c:156
static void setNullValue(PgBenchValue *pv)
Definition: pgbench.c:2092
static bool evaluateExpr(CState *st, PgBenchExpr *expr, PgBenchValue *retval)
Definition: pgbench.c:2835
static void setBoolValue(PgBenchValue *pv, bool bval)
Definition: pgbench.c:2100
static bool valueTruth(PgBenchValue *pval)
Definition: pgbench.c:2022
static bool coerceToBool(PgBenchValue *pval, bool *bval)
Definition: pgbench.c:2002
@ PGBT_NULL
Definition: pgbench.h:37
@ PGBENCH_AND
Definition: pgbench.h:87
@ PGBENCH_OR
Definition: pgbench.h:88
@ PGBENCH_CASE
Definition: pgbench.h:100

References a1, a2, generate_unaccent_rules::args, Assert(), coerceToBool(), evaluateExpr(), isLazyFunc(), PGBENCH_AND, PGBENCH_CASE, PGBENCH_OR, PGBT_NULL, setBoolValue(), setNullValue(), and valueTruth().

Referenced by evalFunc().

◆ evalStandardFunc()

static bool evalStandardFunc ( CState st,
PgBenchFunction  func,
PgBenchExprLink args,
PgBenchValue retval 
)
static

Definition at line 2247 of file pgbench.c.

2251 {
2252  /* evaluate all function arguments */
2253  int nargs = 0;
2254  PgBenchExprLink *l = args;
2255  bool has_null = false;
2256 
2257  /*
2258  * This value is double braced to workaround GCC bug 53119, which seems to
2259  * exist at least on gcc (Debian 4.7.2-5) 4.7.2, 32-bit.
2260  */
2261  PgBenchValue vargs[MAX_FARGS] = {{0}};
2262 
2263  for (nargs = 0; nargs < MAX_FARGS && l != NULL; nargs++, l = l->next)
2264  {
2265  if (!evaluateExpr(st, l->expr, &vargs[nargs]))
2266  return false;
2267  has_null |= vargs[nargs].type == PGBT_NULL;
2268  }
2269 
2270  if (l != NULL)
2271  {
2272  pg_log_error("too many function arguments, maximum is %d", MAX_FARGS);
2273  return false;
2274  }
2275 
2276  /* NULL arguments */
2277  if (has_null && func != PGBENCH_IS && func != PGBENCH_DEBUG)
2278  {
2279  setNullValue(retval);
2280  return true;
2281  }
2282 
2283  /* then evaluate function */
2284  switch (func)
2285  {
2286  /* overloaded operators */
2287  case PGBENCH_ADD:
2288  case PGBENCH_SUB:
2289  case PGBENCH_MUL:
2290  case PGBENCH_DIV:
2291  case PGBENCH_MOD:
2292  case PGBENCH_EQ:
2293  case PGBENCH_NE:
2294  case PGBENCH_LE:
2295  case PGBENCH_LT:
2296  {
2297  PgBenchValue *lval = &vargs[0],
2298  *rval = &vargs[1];
2299 
2300  Assert(nargs == 2);
2301 
2302  /* overloaded type management, double if some double */
2303  if ((lval->type == PGBT_DOUBLE ||
2304  rval->type == PGBT_DOUBLE) && func != PGBENCH_MOD)
2305  {
2306  double ld,
2307  rd;
2308 
2309  if (!coerceToDouble(lval, &ld) ||
2310  !coerceToDouble(rval, &rd))
2311  return false;
2312 
2313  switch (func)
2314  {
2315  case PGBENCH_ADD:
2316  setDoubleValue(retval, ld + rd);
2317  return true;
2318 
2319  case PGBENCH_SUB:
2320  setDoubleValue(retval, ld - rd);
2321  return true;
2322 
2323  case PGBENCH_MUL:
2324  setDoubleValue(retval, ld * rd);
2325  return true;
2326 
2327  case PGBENCH_DIV:
2328  setDoubleValue(retval, ld / rd);
2329  return true;
2330 
2331  case PGBENCH_EQ:
2332  setBoolValue(retval, ld == rd);
2333  return true;
2334 
2335  case PGBENCH_NE:
2336  setBoolValue(retval, ld != rd);
2337  return true;
2338 
2339  case PGBENCH_LE:
2340  setBoolValue(retval, ld <= rd);
2341  return true;
2342 
2343  case PGBENCH_LT:
2344  setBoolValue(retval, ld < rd);
2345  return true;
2346 
2347  default:
2348  /* cannot get here */
2349  Assert(0);
2350  }
2351  }
2352  else /* we have integer operands, or % */
2353  {
2354  int64 li,
2355  ri,
2356  res;
2357 
2358  if (!coerceToInt(lval, &li) ||
2359  !coerceToInt(rval, &ri))
2360  return false;
2361 
2362  switch (func)
2363  {
2364  case PGBENCH_ADD:
2365  if (pg_add_s64_overflow(li, ri, &res))
2366  {
2367  pg_log_error("bigint add out of range");
2368  return false;
2369  }
2370  setIntValue(retval, res);
2371  return true;
2372 
2373  case PGBENCH_SUB:
2374  if (pg_sub_s64_overflow(li, ri, &res))
2375  {
2376  pg_log_error("bigint sub out of range");
2377  return false;
2378  }
2379  setIntValue(retval, res);
2380  return true;
2381 
2382  case PGBENCH_MUL:
2383  if (pg_mul_s64_overflow(li, ri, &res))
2384  {
2385  pg_log_error("bigint mul out of range");
2386  return false;
2387  }
2388  setIntValue(retval, res);
2389  return true;
2390 
2391  case PGBENCH_EQ:
2392  setBoolValue(retval, li == ri);
2393  return true;
2394 
2395  case PGBENCH_NE:
2396  setBoolValue(retval, li != ri);
2397  return true;
2398 
2399  case PGBENCH_LE:
2400  setBoolValue(retval, li <= ri);
2401  return true;
2402 
2403  case PGBENCH_LT:
2404  setBoolValue(retval, li < ri);
2405  return true;
2406 
2407  case PGBENCH_DIV:
2408  case PGBENCH_MOD:
2409  if (ri == 0)
2410  {
2411  pg_log_error("division by zero");
2412  return false;
2413  }
2414  /* special handling of -1 divisor */
2415  if (ri == -1)
2416  {
2417  if (func == PGBENCH_DIV)
2418  {
2419  /* overflow check (needed for INT64_MIN) */
2420  if (li == PG_INT64_MIN)
2421  {
2422  pg_log_error("bigint div out of range");
2423  return false;
2424  }
2425  else
2426  setIntValue(retval, -li);
2427  }
2428  else
2429  setIntValue(retval, 0);
2430  return true;
2431  }
2432  /* else divisor is not -1 */
2433  if (func == PGBENCH_DIV)
2434  setIntValue(retval, li / ri);
2435  else /* func == PGBENCH_MOD */
2436  setIntValue(retval, li % ri);
2437 
2438  return true;
2439 
2440  default:
2441  /* cannot get here */
2442  Assert(0);
2443  }
2444  }
2445 
2446  Assert(0);
2447  return false; /* NOTREACHED */
2448  }
2449 
2450  /* integer bitwise operators */
2451  case PGBENCH_BITAND:
2452  case PGBENCH_BITOR:
2453  case PGBENCH_BITXOR:
2454  case PGBENCH_LSHIFT:
2455  case PGBENCH_RSHIFT:
2456  {
2457  int64 li,
2458  ri;
2459 
2460  if (!coerceToInt(&vargs[0], &li) || !coerceToInt(&vargs[1], &ri))
2461  return false;
2462 
2463  if (func == PGBENCH_BITAND)
2464  setIntValue(retval, li & ri);
2465  else if (func == PGBENCH_BITOR)
2466  setIntValue(retval, li | ri);
2467  else if (func == PGBENCH_BITXOR)
2468  setIntValue(retval, li ^ ri);
2469  else if (func == PGBENCH_LSHIFT)
2470  setIntValue(retval, li << ri);
2471  else if (func == PGBENCH_RSHIFT)
2472  setIntValue(retval, li >> ri);
2473  else /* cannot get here */
2474  Assert(0);
2475 
2476  return true;
2477  }
2478 
2479  /* logical operators */
2480  case PGBENCH_NOT:
2481  {
2482  bool b;
2483 
2484  if (!coerceToBool(&vargs[0], &b))
2485  return false;
2486 
2487  setBoolValue(retval, !b);
2488  return true;
2489  }
2490 
2491  /* no arguments */
2492  case PGBENCH_PI:
2493  setDoubleValue(retval, M_PI);
2494  return true;
2495 
2496  /* 1 overloaded argument */
2497  case PGBENCH_ABS:
2498  {
2499  PgBenchValue *varg = &vargs[0];
2500 
2501  Assert(nargs == 1);
2502 
2503  if (varg->type == PGBT_INT)
2504  {
2505  int64 i = varg->u.ival;
2506 
2507  setIntValue(retval, i < 0 ? -i : i);
2508  }
2509  else
2510  {
2511  double d = varg->u.dval;
2512 
2513  Assert(varg->type == PGBT_DOUBLE);
2514  setDoubleValue(retval, d < 0.0 ? -d : d);
2515  }
2516 
2517  return true;
2518  }
2519 
2520  case PGBENCH_DEBUG:
2521  {
2522  PgBenchValue *varg = &vargs[0];
2523 
2524  Assert(nargs == 1);
2525 
2526  fprintf(stderr, "debug(script=%d,command=%d): ",
2527  st->use_file, st->command + 1);
2528 
2529  if (varg->type == PGBT_NULL)
2530  fprintf(stderr, "null\n");
2531  else if (varg->type == PGBT_BOOLEAN)
2532  fprintf(stderr, "boolean %s\n", varg->u.bval ? "true" : "false");
2533  else if (varg->type == PGBT_INT)
2534  fprintf(stderr, "int " INT64_FORMAT "\n", varg->u.ival);
2535  else if (varg->type == PGBT_DOUBLE)
2536  fprintf(stderr, "double %.*g\n", DBL_DIG, varg->u.dval);
2537  else /* internal error, unexpected type */
2538  Assert(0);
2539 
2540  *retval = *varg;
2541 
2542  return true;
2543  }
2544 
2545  /* 1 double argument */
2546  case PGBENCH_DOUBLE:
2547  case PGBENCH_SQRT:
2548  case PGBENCH_LN:
2549  case PGBENCH_EXP:
2550  {
2551  double dval;
2552 
2553  Assert(nargs == 1);
2554 
2555  if (!coerceToDouble(&vargs[0], &dval))
2556  return false;
2557 
2558  if (func == PGBENCH_SQRT)
2559  dval = sqrt(dval);
2560  else if (func == PGBENCH_LN)
2561  dval = log(dval);
2562  else if (func == PGBENCH_EXP)
2563  dval = exp(dval);
2564  /* else is cast: do nothing */
2565 
2566  setDoubleValue(retval, dval);
2567  return true;
2568  }
2569 
2570  /* 1 int argument */
2571  case PGBENCH_INT:
2572  {
2573  int64 ival;
2574 
2575  Assert(nargs == 1);
2576 
2577  if (!coerceToInt(&vargs[0], &ival))
2578  return false;
2579 
2580  setIntValue(retval, ival);
2581  return true;
2582  }
2583 
2584  /* variable number of arguments */
2585  case PGBENCH_LEAST:
2586  case PGBENCH_GREATEST:
2587  {
2588  bool havedouble;
2589  int i;
2590 
2591  Assert(nargs >= 1);
2592 
2593  /* need double result if any input is double */
2594  havedouble = false;
2595  for (i = 0; i < nargs; i++)
2596  {
2597  if (vargs[i].type == PGBT_DOUBLE)
2598  {
2599  havedouble = true;
2600  break;
2601  }
2602  }
2603  if (havedouble)
2604  {
2605  double extremum;
2606 
2607  if (!coerceToDouble(&vargs[0], &extremum))
2608  return false;
2609  for (i = 1; i < nargs; i++)
2610  {
2611  double dval;
2612 
2613  if (!coerceToDouble(&vargs[i], &dval))
2614  return false;
2615  if (func == PGBENCH_LEAST)
2616  extremum = Min(extremum, dval);
2617  else
2618  extremum = Max(extremum, dval);
2619  }
2620  setDoubleValue(retval, extremum);
2621  }
2622  else
2623  {
2624  int64 extremum;
2625 
2626  if (!coerceToInt(&vargs[0], &extremum))
2627  return false;
2628  for (i = 1; i < nargs; i++)
2629  {
2630  int64 ival;
2631 
2632  if (!coerceToInt(&vargs[i], &ival))
2633  return false;
2634  if (func == PGBENCH_LEAST)
2635  extremum = Min(extremum, ival);
2636  else
2637  extremum = Max(extremum, ival);
2638  }
2639  setIntValue(retval, extremum);
2640  }
2641  return true;
2642  }
2643 
2644  /* random functions */
2645  case PGBENCH_RANDOM:
2649  {
2650  int64 imin,
2651  imax,
2652  delta;
2653 
2654  Assert(nargs >= 2);
2655 
2656  if (!coerceToInt(&vargs[0], &imin) ||
2657  !coerceToInt(&vargs[1], &imax))
2658  return false;
2659 
2660  /* check random range */
2661  if (unlikely(imin > imax))
2662  {
2663  pg_log_error("empty range given to random");
2664  return false;
2665  }
2666  else if (unlikely(pg_sub_s64_overflow(imax, imin, &delta) ||
2667  pg_add_s64_overflow(delta, 1, &delta)))
2668  {
2669  /* prevent int overflows in random functions */
2670  pg_log_error("random range is too large");
2671  return false;
2672  }
2673 
2674  if (func == PGBENCH_RANDOM)
2675  {
2676  Assert(nargs == 2);
2677  setIntValue(retval, getrand(&st->cs_func_rs, imin, imax));
2678  }
2679  else /* gaussian & exponential */
2680  {
2681  double param;
2682 
2683  Assert(nargs == 3);
2684 
2685  if (!coerceToDouble(&vargs[2], &param))
2686  return false;
2687 
2688  if (func == PGBENCH_RANDOM_GAUSSIAN)
2689  {
2690  if (param < MIN_GAUSSIAN_PARAM)
2691  {
2692  pg_log_error("gaussian parameter must be at least %f (not %f)",
2693  MIN_GAUSSIAN_PARAM, param);
2694  return false;
2695  }
2696 
2697  setIntValue(retval,
2699  imin, imax, param));
2700  }
2701  else if (func == PGBENCH_RANDOM_ZIPFIAN)
2702  {
2703  if (param < MIN_ZIPFIAN_PARAM || param > MAX_ZIPFIAN_PARAM)
2704  {
2705  pg_log_error("zipfian parameter must be in range [%.3f, %.0f] (not %f)",
2707  return false;
2708  }
2709 
2710  setIntValue(retval,
2711  getZipfianRand(&st->cs_func_rs, imin, imax, param));
2712  }
2713  else /* exponential */
2714  {
2715  if (param <= 0.0)
2716  {
2717  pg_log_error("exponential parameter must be greater than zero (not %f)",
2718  param);
2719  return false;
2720  }
2721 
2722  setIntValue(retval,
2724  imin, imax, param));
2725  }
2726  }
2727 
2728  return true;
2729  }
2730 
2731  case PGBENCH_POW:
2732  {
2733  PgBenchValue *lval = &vargs[0];
2734  PgBenchValue *rval = &vargs[1];
2735  double ld,
2736  rd;
2737 
2738  Assert(nargs == 2);
2739 
2740  if (!coerceToDouble(lval, &ld) ||
2741  !coerceToDouble(rval, &rd))
2742  return false;
2743 
2744  setDoubleValue(retval, pow(ld, rd));
2745 
2746  return true;
2747  }
2748 
2749  case PGBENCH_IS:
2750  {
2751  Assert(nargs == 2);
2752 
2753  /*
2754  * note: this simple implementation is more permissive than
2755  * SQL
2756  */
2757  setBoolValue(retval,
2758  vargs[0].type == vargs[1].type &&
2759  vargs[0].u.bval == vargs[1].u.bval);
2760  return true;
2761  }
2762 
2763  /* hashing */
2764  case PGBENCH_HASH_FNV1A:
2765  case PGBENCH_HASH_MURMUR2:
2766  {
2767  int64 val,
2768  seed;
2769 
2770  Assert(nargs == 2);
2771 
2772  if (!coerceToInt(&vargs[0], &val) ||
2773  !coerceToInt(&vargs[1], &seed))
2774  return false;
2775 
2776  if (func == PGBENCH_HASH_MURMUR2)
2777  setIntValue(retval, getHashMurmur2(val, seed));
2778  else if (func == PGBENCH_HASH_FNV1A)
2779  setIntValue(retval, getHashFnv1a(val, seed));
2780  else
2781  /* cannot get here */
2782  Assert(0);
2783 
2784  return true;
2785  }
2786 
2787  case PGBENCH_PERMUTE:
2788  {
2789  int64 val,
2790  size,
2791  seed;
2792 
2793  Assert(nargs == 3);
2794 
2795  if (!coerceToInt(&vargs[0], &val) ||
2796  !coerceToInt(&vargs[1], &size) ||
2797  !coerceToInt(&vargs[2], &seed))
2798  return false;
2799 
2800  if (size <= 0)
2801  {
2802  pg_log_error("permute size parameter must be greater than zero");
2803  return false;
2804  }
2805 
2806  setIntValue(retval, permute(val, size, seed));
2807  return true;
2808  }
2809 
2810  default:
2811  /* cannot get here */
2812  Assert(0);
2813  /* dead code to avoid a compiler warning */
2814  return false;
2815  }
#define Min(x, y)
Definition: c.h:993
#define Max(x, y)
Definition: c.h:987
#define PG_INT64_MIN
Definition: c.h:580
#define unlikely(x)
Definition: c.h:300
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:219
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:188
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:161
static int64 getZipfianRand(pg_prng_state *state, int64 min, int64 max, double s)
Definition: pgbench.c:1229
static void setIntValue(PgBenchValue *pv, int64 ival)
Definition: pgbench.c:2108
static bool coerceToInt(PgBenchValue *pval, int64 *ival)
Definition: pgbench.c:2043
static int64 getExponentialRand(pg_prng_state *state, int64 min, int64 max, double parameter)
Definition: pgbench.c:1111
static void setDoubleValue(PgBenchValue *pv, double dval)
Definition: pgbench.c:2116
#define MIN_ZIPFIAN_PARAM
Definition: pgbench.c:170
static int64 permute(const int64 val, const int64 isize, const int64 seed)
Definition: pgbench.c:1301
#define MAX_FARGS
Definition: pgbench.c:2240
static int64 getHashMurmur2(int64 val, uint64 seed)
Definition: pgbench.c:1268
static int64 getGaussianRand(pg_prng_state *state, int64 min, int64 max, double parameter)
Definition: pgbench.c:1135
#define MIN_GAUSSIAN_PARAM
Definition: pgbench.c:168
#define M_PI
Definition: pgbench.c:73
static int64 getHashFnv1a(int64 val, uint64 seed)
Definition: pgbench.c:1243
static bool coerceToDouble(PgBenchValue *pval, double *dval)
Definition: pgbench.c:2071
#define MAX_ZIPFIAN_PARAM
Definition: pgbench.c:171
@ PGBENCH_DIV
Definition: pgbench.h:70
@ 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_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
const char * type

References generate_unaccent_rules::args, Assert(), b, PgBenchValue::bval, coerceToBool(), coerceToDouble(), coerceToInt(), CState::command, CState::cs_func_rs, PgBenchValue::dval, evaluateExpr(), PgBenchExprLink::expr, fprintf, getExponentialRand(), getGaussianRand(), getHashFnv1a(), getHashMurmur2(), getrand(), getZipfianRand(), i, INT64_FORMAT, PgBenchValue::ival, M_PI, Max, MAX_FARGS, MAX_ZIPFIAN_PARAM, Min, MIN_GAUSSIAN_PARAM, MIN_ZIPFIAN_PARAM, PgBenchExprLink::next, permute(), pg_add_s64_overflow(), PG_INT64_MIN, pg_log_error, pg_mul_s64_overflow(), pg_sub_s64_overflow(), PGBENCH_ABS, PGBENCH_ADD, PGBENCH_BITAND, PGBENCH_BITOR, PGBENCH_BITXOR, PGBENCH_DEBUG, PGBENCH_DIV, PGBENCH_DOUBLE, PGBENCH_EQ, PGBENCH_EXP, PGBENCH_GREATEST, PGBENCH_HASH_FNV1A, PGBENCH_HASH_MURMUR2, PGBENCH_INT, PGBENCH_IS, PGBENCH_LE, PGBENCH_LEAST, PGBENCH_LN, PGBENCH_LSHIFT, PGBENCH_LT, PGBENCH_MOD, PGBENCH_MUL, PGBENCH_NE, PGBENCH_NOT, PGBENCH_PERMUTE, PGBENCH_PI, PGBENCH_POW, PGBENCH_RANDOM, PGBENCH_RANDOM_EXPONENTIAL, PGBENCH_RANDOM_GAUSSIAN, PGBENCH_RANDOM_ZIPFIAN, PGBENCH_RSHIFT, PGBENCH_SQRT, PGBENCH_SUB, PGBT_BOOLEAN, PGBT_DOUBLE, PGBT_INT, PGBT_NULL, res, setBoolValue(), setDoubleValue(), setIntValue(), setNullValue(), type, PgBenchValue::type, PgBenchValue::u, unlikely, CState::use_file, and val.

Referenced by evalFunc().

◆ evaluateExpr()

static bool evaluateExpr ( CState st,
PgBenchExpr expr,
PgBenchValue retval 
)
static

Definition at line 2835 of file pgbench.c.

2837 {
2838  switch (expr->etype)
2839  {
2840  case ENODE_CONSTANT:
2841  {
2842  *retval = expr->u.constant;
2843  return true;
2844  }
2845 
2846  case ENODE_VARIABLE:
2847  {
2848  Variable *var;
2849 
2850  if ((var = lookupVariable(&st->variables, expr->u.variable.varname)) == NULL)
2851  {
2852  pg_log_error("undefined variable \"%s\"", expr->u.variable.varname);
2853  return false;
2854  }
2855 
2856  if (!makeVariableValue(var))
2857  return false;
2858 
2859  *retval = var->value;
2860  return true;
2861  }
2862 
2863  case ENODE_FUNCTION:
2864  return evalFunc(st,
2865  expr->u.function.function,
2866  expr->u.function.args,
2867  retval);
2868 
2869  default:
2870  /* internal error which should never occur */
2871  pg_fatal("unexpected enode type in evaluation: %d", expr->etype);
2872  }
static Variable * lookupVariable(Variables *variables, char *name)
Definition: pgbench.c:1602
static bool evalFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2819
static bool makeVariableValue(Variable *var)
Definition: pgbench.c:1662
@ ENODE_VARIABLE
Definition: pgbench.h:60
@ ENODE_CONSTANT
Definition: pgbench.h:59
@ ENODE_FUNCTION
Definition: pgbench.h:61
Variables variables
Definition: pgbench.c:613
PgBenchValue constant
Definition: pgbench.h:115
PgBenchFunction function
Definition: pgbench.h:122
PgBenchExprType etype
Definition: pgbench.h:112
struct PgBenchExpr::@34::@35 variable
union PgBenchExpr::@34 u
PgBenchValue value
Definition: pgbench.c:325

References PgBenchExpr::constant, ENODE_CONSTANT, ENODE_FUNCTION, ENODE_VARIABLE, PgBenchExpr::etype, evalFunc(), PgBenchExpr::function, lookupVariable(), makeVariableValue(), pg_fatal, pg_log_error, PgBenchExpr::u, Variable::value, PgBenchExpr::variable, and CState::variables.

Referenced by evalLazyFunc(), evalStandardFunc(), and executeMetaCommand().

◆ evaluateSleep()

static bool evaluateSleep ( Variables variables,
int  argc,
char **  argv,
int *  usecs 
)
static

Definition at line 3381 of file pgbench.c.

3383 {
3384  char *var;
3385  int usec;
3386 
3387  if (*argv[1] == ':')
3388  {
3389  if ((var = getVariable(variables, argv[1] + 1)) == NULL)
3390  {
3391  pg_log_error("%s: undefined variable \"%s\"", argv[0], argv[1] + 1);
3392  return false;
3393  }
3394 
3395  usec = atoi(var);
3396 
3397  /* Raise an error if the value of a variable is not a number */
3398  if (usec == 0 && !isdigit((unsigned char) *var))
3399  {
3400  pg_log_error("%s: invalid sleep time \"%s\" for variable \"%s\"",
3401  argv[0], var, argv[1] + 1);
3402  return false;
3403  }
3404  }
3405  else
3406  usec = atoi(argv[1]);
3407 
3408  if (argc > 2)
3409  {
3410  if (pg_strcasecmp(argv[2], "ms") == 0)
3411  usec *= 1000;
3412  else if (pg_strcasecmp(argv[2], "s") == 0)
3413  usec *= 1000000;
3414  }
3415  else
3416  usec *= 1000000;
3417 
3418  *usecs = usec;
3419  return true;
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

References getVariable(), pg_log_error, and pg_strcasecmp().

Referenced by executeMetaCommand().

◆ executeMetaCommand()

static ConnectionStateEnum executeMetaCommand ( CState st,
pg_time_usec_t now 
)
static

Definition at line 4283 of file pgbench.c.

4285 {
4286  Command *command = sql_script[st->use_file].commands[st->command];
4287  int argc;
4288  char **argv;
4289 
4290  Assert(command != NULL && command->type == META_COMMAND);
4291 
4292  argc = command->argc;
4293  argv = command->argv;
4294 
4296  {
4298 
4299  initPQExpBuffer(&buf);
4300 
4301  printfPQExpBuffer(&buf, "client %d executing \\%s", st->id, argv[0]);
4302  for (int i = 1; i < argc; i++)
4303  appendPQExpBuffer(&buf, " %s", argv[i]);
4304 
4305  pg_log_debug("%s", buf.data);
4306 
4307  termPQExpBuffer(&buf);
4308  }
4309 
4310  if (command->meta == META_SLEEP)
4311  {
4312  int usec;
4313 
4314  /*
4315  * A \sleep doesn't execute anything, we just get the delay from the
4316  * argument, and enter the CSTATE_SLEEP state. (The per-command
4317  * latency will be recorded in CSTATE_SLEEP state, not here, after the
4318  * delay has elapsed.)
4319  */
4320  if (!evaluateSleep(&st->variables, argc, argv, &usec))
4321  {
4322  commandFailed(st, "sleep", "execution of meta-command failed");
4323  return CSTATE_ABORTED;
4324  }
4325 
4327  st->sleep_until = (*now) + usec;
4328  return CSTATE_SLEEP;
4329  }
4330  else if (command->meta == META_SET)
4331  {
4332  PgBenchExpr *expr = command->expr;
4333  PgBenchValue result;
4334 
4335  if (!evaluateExpr(st, expr, &result))
4336  {
4337  commandFailed(st, argv[0], "evaluation of meta-command failed");
4338  return CSTATE_ABORTED;
4339  }
4340 
4341  if (!putVariableValue(&st->variables, argv[0], argv[1], &result))
4342  {
4343  commandFailed(st, "set", "assignment of meta-command failed");
4344  return CSTATE_ABORTED;
4345  }
4346  }
4347  else if (command->meta == META_IF)
4348  {
4349  /* backslash commands with an expression to evaluate */
4350  PgBenchExpr *expr = command->expr;
4351  PgBenchValue result;
4352  bool cond;
4353 
4354  if (!evaluateExpr(st, expr, &result))
4355  {
4356  commandFailed(st, argv[0], "evaluation of meta-command failed");
4357  return CSTATE_ABORTED;
4358  }
4359 
4360  cond = valueTruth(&result);
4362  }
4363  else if (command->meta == META_ELIF)
4364  {
4365  /* backslash commands with an expression to evaluate */
4366  PgBenchExpr *expr = command->expr;
4367  PgBenchValue result;
4368  bool cond;
4369 
4371  {
4372  /* elif after executed block, skip eval and wait for endif. */
4374  return CSTATE_END_COMMAND;
4375  }
4376 
4377  if (!evaluateExpr(st, expr, &result))
4378  {
4379  commandFailed(st, argv[0], "evaluation of meta-command failed");
4380  return CSTATE_ABORTED;
4381  }
4382 
4383  cond = valueTruth(&result);
4386  }
4387  else if (command->meta == META_ELSE)
4388  {
4389  switch (conditional_stack_peek(st->cstack))
4390  {
4391  case IFSTATE_TRUE:
4393  break;
4394  case IFSTATE_FALSE: /* inconsistent if active */
4395  case IFSTATE_IGNORED: /* inconsistent if active */
4396  case IFSTATE_NONE: /* else without if */
4397  case IFSTATE_ELSE_TRUE: /* else after else */
4398  case IFSTATE_ELSE_FALSE: /* else after else */
4399  default:
4400  /* dead code if conditional check is ok */
4401  Assert(false);
4402  }
4403  }
4404  else if (command->meta == META_ENDIF)
4405  {
4408  }
4409  else if (command->meta == META_SETSHELL)
4410  {
4411  if (!runShellCommand(&st->variables, argv[1], argv + 2, argc - 2))
4412  {
4413  commandFailed(st, "setshell", "execution of meta-command failed");
4414  return CSTATE_ABORTED;
4415  }
4416  }
4417  else if (command->meta == META_SHELL)
4418  {
4419  if (!runShellCommand(&st->variables, NULL, argv + 1, argc - 1))
4420  {
4421  commandFailed(st, "shell", "execution of meta-command failed");
4422  return CSTATE_ABORTED;
4423  }
4424  }
4425  else if (command->meta == META_STARTPIPELINE)
4426  {
4427  /*
4428  * In pipeline mode, we use a workflow based on libpq pipeline
4429  * functions.
4430  */
4431  if (querymode == QUERY_SIMPLE)
4432  {
4433  commandFailed(st, "startpipeline", "cannot use pipeline mode with the simple query protocol");
4434  return CSTATE_ABORTED;
4435  }
4436 
4437  /*
4438  * If we're in prepared-query mode, we need to prepare all the
4439  * commands that are inside the pipeline before we actually start the
4440  * pipeline itself. This solves the problem that running BEGIN
4441  * ISOLATION LEVEL SERIALIZABLE in a pipeline would fail due to a
4442  * snapshot having been acquired by the prepare within the pipeline.
4443  */
4444  if (querymode == QUERY_PREPARED)
4446 
4447  if (PQpipelineStatus(st->con) != PQ_PIPELINE_OFF)
4448  {
4449  commandFailed(st, "startpipeline", "already in pipeline mode");
4450  return CSTATE_ABORTED;
4451  }
4452  if (PQenterPipelineMode(st->con) == 0)
4453  {
4454  commandFailed(st, "startpipeline", "failed to enter pipeline mode");
4455  return CSTATE_ABORTED;
4456  }
4457  }
4458  else if (command->meta == META_SYNCPIPELINE)
4459  {
4460  if (PQpipelineStatus(st->con) != PQ_PIPELINE_ON)
4461  {
4462  commandFailed(st, "syncpipeline", "not in pipeline mode");
4463  return CSTATE_ABORTED;
4464  }
4465  if (PQsendPipelineSync(st->con) == 0)
4466  {
4467  commandFailed(st, "syncpipeline", "failed to send a pipeline sync");
4468  return CSTATE_ABORTED;
4469  }
4470  st->num_syncs++;
4471  }
4472  else if (command->meta == META_ENDPIPELINE)
4473  {
4474  if (PQpipelineStatus(st->con) != PQ_PIPELINE_ON)
4475  {
4476  commandFailed(st, "endpipeline", "not in pipeline mode");
4477  return CSTATE_ABORTED;
4478  }
4479  if (!PQpipelineSync(st->con))
4480  {
4481  commandFailed(st, "endpipeline", "failed to send a pipeline sync");
4482  return CSTATE_ABORTED;
4483  }
4484  st->num_syncs++;
4485  /* Now wait for the PGRES_PIPELINE_SYNC and exit pipeline mode there */
4486  /* collect pending results before getting out of pipeline mode */
4487  return CSTATE_WAIT_RESULT;
4488  }
4489 
4490  /*
4491  * executing the expression or shell command might have taken a
4492  * non-negligible amount of time, so reset 'now'
4493  */
4494  *now = 0;
4495 
4496  return CSTATE_END_COMMAND;
int PQenterPipelineMode(PGconn *conn)
Definition: fe-exec.c:3004
int PQsendPipelineSync(PGconn *conn)
Definition: fe-exec.c:3242
enum pg_log_level __pg_log_level
Definition: logging.c:21
@ PG_LOG_DEBUG
Definition: logging.h:26
static QueryMode querymode
Definition: pgbench.c:712
static void prepareCommandsInPipeline(CState *st)
Definition: pgbench.c:3120
static bool runShellCommand(Variables *variables, char *variable, char **argv, int argc)
Definition: pgbench.c:2920
static bool evaluateSleep(Variables *variables, int argc, char **argv, int *usecs)
Definition: pgbench.c:3381
static bool putVariableValue(Variables *variables, const char *context, char *name, const PgBenchValue *value)
Definition: pgbench.c:1850
pg_time_usec_t sleep_until
Definition: pgbench.c:617
int num_syncs
Definition: pgbench.c:610

References __pg_log_level, appendPQExpBuffer(), Command::argc, Command::argv, Assert(), buf, CState::command, commandFailed(), ParsedScript::commands, CState::con, conditional_stack_empty(), conditional_stack_peek(), conditional_stack_poke(), conditional_stack_pop(), conditional_stack_push(), CState::cstack, CSTATE_ABORTED, CSTATE_END_COMMAND, CSTATE_SLEEP, CSTATE_WAIT_RESULT, evaluateExpr(), evaluateSleep(), Command::expr, i, CState::id, IFSTATE_ELSE_FALSE, IFSTATE_ELSE_TRUE, IFSTATE_FALSE, IFSTATE_IGNORED, IFSTATE_NONE, IFSTATE_TRUE, initPQExpBuffer(), Command::meta, META_COMMAND, META_ELIF, META_ELSE, META_ENDIF, META_ENDPIPELINE, META_IF, META_SET, META_SETSHELL, META_SHELL, META_SLEEP, META_STARTPIPELINE, META_SYNCPIPELINE, now(), CState::num_syncs, PG_LOG_DEBUG, pg_log_debug, pg_time_now_lazy(), PQ_PIPELINE_OFF, PQ_PIPELINE_ON, PQenterPipelineMode(), PQpipelineStatus(), PQpipelineSync(), PQsendPipelineSync(), prepareCommandsInPipeline(), printfPQExpBuffer(), putVariableValue(), QUERY_PREPARED, QUERY_SIMPLE, querymode, runShellCommand(), CState::sleep_until, sql_script, termPQExpBuffer(), Command::type, unlikely, CState::use_file, valueTruth(), and CState::variables.

Referenced by advanceConnectionState().

◆ executeStatement()

static void executeStatement ( PGconn con,
const char *  sql 
)
static

Definition at line 1498 of file pgbench.c.

1500 {
1501  PGresult *res;
1502 
1503  res = PQexec(con, sql);
1505  {
1506  pg_log_error("query failed: %s", PQerrorMessage(con));
1507  pg_log_error_detail("Query was: %s", sql);
1508  exit(1);
1509  }
1510  PQclear(res);
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2224

References exit(), pg_log_error, pg_log_error_detail, PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQexec(), PQresultStatus(), and res.

Referenced by createPartitions(), initCreateFKeys(), initCreatePKeys(), initCreateTables(), initDropTables(), initGenerateDataClientSide(), initGenerateDataServerSide(), initTruncateTables(), and initVacuum().

◆ findBuiltin()

static const BuiltinScript* findBuiltin ( const char *  name)
static

Definition at line 6118 of file pgbench.c.

6120 {
6121  int i,
6122  found = 0,
6123  len = strlen(name);
6124  const BuiltinScript *result = NULL;
6125 
6126  for (i = 0; i < lengthof(builtin_script); i++)
6127  {
6128  if (strncmp(builtin_script[i].name, name, len) == 0)
6129  {
6130  result = &builtin_script[i];
6131  found++;
6132  }
6133  }
6134 
6135  /* ok, unambiguous result */
6136  if (found == 1)
6137  return result;
6138 
6139  /* error cases */
6140  if (found == 0)
6141  pg_log_error("no builtin script found for name \"%s\"", name);
6142  else /* found > 1 */
6143  pg_log_error("ambiguous builtin name: %d builtin scripts found for prefix \"%s\"", found, name);
6144 
6146  exit(1);
#define lengthof(array)
Definition: c.h:777
const void size_t len
static void listAvailableScripts(void)
Definition: pgbench.c:6106
static const BuiltinScript builtin_script[]
Definition: pgbench.c:779

References builtin_script, exit(), i, len, lengthof, listAvailableScripts(), name, and pg_log_error.

Referenced by main().

◆ finishCon()

static void finishCon ( CState st)
static

Definition at line 7686 of file pgbench.c.

7688 {
7689  if (st->con != NULL)
7690  {
7691  PQfinish(st->con);
7692  st->con = NULL;
7693  }

References CState::con, and PQfinish().

Referenced by advanceConnectionState(), and disconnect_all().

◆ free_command()

static void free_command ( Command command)
static

Definition at line 5576 of file pgbench.c.

5578 {
5579  termPQExpBuffer(&command->lines);
5580  pg_free(command->first_line);
5581  for (int i = 0; i < command->argc; i++)
5582  pg_free(command->argv[i]);
5583  pg_free(command->varprefix);
5584 
5585  /*
5586  * It should also free expr recursively, but this is currently not needed
5587  * as only gset commands (which do not have an expression) are freed.
5588  */
5589  pg_free(command);

References Command::argc, Command::argv, Command::first_line, i, Command::lines, pg_free(), termPQExpBuffer(), and Command::varprefix.

Referenced by ParseScript().

◆ free_socket_set()

static void free_socket_set ( socket_set sa)
static

Definition at line 7857 of file pgbench.c.

7859 {
7860  pg_free(sa);

References pg_free().

Referenced by threadRun().

◆ getExponentialRand()

static int64 getExponentialRand ( pg_prng_state state,
int64  min,
int64  max,
double  parameter 
)
static

Definition at line 1111 of file pgbench.c.

1114 {
1115  double cut,
1116  uniform,
1117  rand;
1118 
1119  /* abort if wrong parameter, but must really be checked beforehand */
1120  Assert(parameter > 0.0);
1121  cut = exp(-parameter);
1122  /* pg_prng_double value in [0, 1), uniform in (0, 1] */
1123  uniform = 1.0 - pg_prng_double(state);
1124 
1125  /*
1126  * inner expression in (cut, 1] (if parameter > 0), rand in [0, 1)
1127  */
1128  Assert((1.0 - cut) != 0.0);
1129  rand = -log(cut + (1.0 - cut) * uniform) / parameter;
1130  /* return int64 random number within between min and max */
1131  return min + (int64) ((max - min + 1) * rand);

References Assert(), and pg_prng_double().

Referenced by evalStandardFunc().

◆ getFailures()

static int64 getFailures ( const StatsData stats)
static

Definition at line 4502 of file pgbench.c.

4504 {
4505  return (stats->serialization_failures +
4506  stats->deadlock_failures);

References StatsData::deadlock_failures, and StatsData::serialization_failures.

Referenced by printProgressReport(), and printResults().

◆ getGaussianRand()

static int64 getGaussianRand ( pg_prng_state state,
int64  min,
int64  max,
double  parameter 
)
static

Definition at line 1135 of file pgbench.c.

1138 {
1139  double stdev;
1140  double rand;
1141 
1142  /* abort if parameter is too low, but must really be checked beforehand */
1143  Assert(parameter >= MIN_GAUSSIAN_PARAM);
1144 
1145  /*
1146  * Get normally-distributed random number in the range -parameter <= stdev
1147  * < parameter.
1148  *
1149  * This loop is executed until the number is in the expected range.
1150  *
1151  * As the minimum parameter is 2.0, the probability of looping is low:
1152  * sqrt(-2 ln(r)) <= 2 => r >= e^{-2} ~ 0.135, then when taking the
1153  * average sinus multiplier as 2/pi, we have a 8.6% looping probability in
1154  * the worst case. For a parameter value of 5.0, the looping probability
1155  * is about e^{-5} * 2 / pi ~ 0.43%.
1156  */
1157  do
1158  {
1159  stdev = pg_prng_double_normal(state);
1160  }
1161  while (stdev < -parameter || stdev >= parameter);
1162 
1163  /* stdev is in [-parameter, parameter), normalization to [0,1) */
1164  rand = (stdev + parameter) / (parameter * 2.0);
1165 
1166  /* return int64 random number within between min and max */
1167  return min + (int64) ((max - min + 1) * rand);
double pg_prng_double_normal(pg_prng_state *state)
Definition: pg_prng.c:254

References Assert(), MIN_GAUSSIAN_PARAM, and pg_prng_double_normal().

Referenced by evalStandardFunc().

◆ getHashFnv1a()

static int64 getHashFnv1a ( int64  val,
uint64  seed 
)
static

Definition at line 1243 of file pgbench.c.

1245 {
1246  int64 result;
1247  int i;
1248 
1249  result = FNV_OFFSET_BASIS ^ seed;
1250  for (i = 0; i < 8; ++i)
1251  {
1252  int32 octet = val & 0xff;
1253 
1254  val = val >> 8;
1255  result = result ^ octet;
1256  result = result * FNV_PRIME;
1257  }
1258 
1259  return result;
signed int int32
Definition: c.h:483
#define FNV_OFFSET_BASIS
Definition: pgbench.c:84
#define FNV_PRIME
Definition: pgbench.c:83

References FNV_OFFSET_BASIS, FNV_PRIME, i, and val.

Referenced by evalStandardFunc().

◆ getHashMurmur2()

static int64 getHashMurmur2 ( int64  val,
uint64  seed 
)
static

Definition at line 1268 of file pgbench.c.

1270 {
1271  uint64 result = seed ^ MM2_MUL_TIMES_8; /* sizeof(int64) */
1272  uint64 k = (uint64) val;
1273 
1274  k *= MM2_MUL;
1275  k ^= k >> MM2_ROT;
1276  k *= MM2_MUL;
1277 
1278  result ^= k;
1279  result *= MM2_MUL;
1280 
1281  result ^= result >> MM2_ROT;
1282  result *= MM2_MUL;
1283  result ^= result >> MM2_ROT;
1284 
1285  return (int64) result;
#define MM2_MUL_TIMES_8
Definition: pgbench.c:86
#define MM2_ROT
Definition: pgbench.c:87
#define MM2_MUL
Definition: pgbench.c:85

References MM2_MUL, MM2_MUL_TIMES_8, MM2_ROT, and val.

Referenced by evalStandardFunc().

◆ getMetaCommand()

static MetaCommand getMetaCommand ( const char *  cmd)
static

Definition at line 2878 of file pgbench.c.

2880 {
2881  MetaCommand mc;
2882 
2883  if (cmd == NULL)
2884  mc = META_NONE;
2885  else if (pg_strcasecmp(cmd, "set") == 0)
2886  mc = META_SET;
2887  else if (pg_strcasecmp(cmd, "setshell") == 0)
2888  mc = META_SETSHELL;
2889  else if (pg_strcasecmp(cmd, "shell") == 0)
2890  mc = META_SHELL;
2891  else if (pg_strcasecmp(cmd, "sleep") == 0)
2892  mc = META_SLEEP;
2893  else if (pg_strcasecmp(cmd, "if") == 0)
2894  mc = META_IF;
2895  else if (pg_strcasecmp(cmd, "elif") == 0)
2896  mc = META_ELIF;
2897  else if (pg_strcasecmp(cmd, "else") == 0)
2898  mc = META_ELSE;
2899  else if (pg_strcasecmp(cmd, "endif") == 0)
2900  mc = META_ENDIF;
2901  else if (pg_strcasecmp(cmd, "gset") == 0)
2902  mc = META_GSET;
2903  else if (pg_strcasecmp(cmd, "aset") == 0)
2904  mc = META_ASET;
2905  else if (pg_strcasecmp(cmd, "startpipeline") == 0)
2906  mc = META_STARTPIPELINE;
2907  else if (pg_strcasecmp(cmd, "syncpipeline") == 0)
2908  mc = META_SYNCPIPELINE;
2909  else if (pg_strcasecmp(cmd, "endpipeline") == 0)
2910  mc = META_ENDPIPELINE;
2911  else
2912  mc = META_NONE;
2913  return mc;
MetaCommand
Definition: pgbench.c:687

References META_ASET, META_ELIF, META_ELSE, META_ENDIF, META_ENDPIPELINE, META_GSET, META_IF, META_NONE, META_SET, META_SETSHELL, META_SHELL, META_SLEEP, META_STARTPIPELINE, META_SYNCPIPELINE, and pg_strcasecmp().

Referenced by process_backslash_command().

◆ getPoissonRand()

static int64 getPoissonRand ( pg_prng_state state,
double  center 
)
static

Definition at line 1177 of file pgbench.c.

1179 {
1180  /*
1181  * Use inverse transform sampling to generate a value > 0, such that the
1182  * expected (i.e. average) value is the given argument.
1183  */
1184  double uniform;
1185 
1186  /* pg_prng_double value in [0, 1), uniform in (0, 1] */
1187  uniform = 1.0 - pg_prng_double(state);
1188 
1189  return (int64) (-log(uniform) * center + 0.5);

References pg_prng_double().

Referenced by advanceConnectionState().

◆ getQueryParams()

static void getQueryParams ( Variables variables,
const Command command,
const char **  params 
)
static

Definition at line 1970 of file pgbench.c.

1973 {
1974  int i;
1975 
1976  for (i = 0; i < command->argc - 1; i++)
1977  params[i] = getVariable(variables, command->argv[i + 1]);

References Command::argc, Command::argv, getVariable(), and i.

Referenced by sendCommand().

◆ getrand()

static int64 getrand ( pg_prng_state state,
int64  min,
int64  max 
)
static

Definition at line 1100 of file pgbench.c.

1102 {
1103  return min + (int64) pg_prng_uint64_range(state, 0, max - min);
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:144

References pg_prng_uint64_range().

Referenced by chooseScript(), and evalStandardFunc().

◆ getResultString()

static const char* getResultString ( bool  skipped,
EStatus  estatus 
)
static

Definition at line 4513 of file pgbench.c.

4515 {
4516  if (skipped)
4517  return "skipped";
4518  else if (failures_detailed)
4519  {
4520  switch (estatus)
4521  {
4523  return "serialization";
4525  return "deadlock";
4526  default:
4527  /* internal error which should never occur */
4528  pg_fatal("unexpected error status: %d", estatus);
4529  }
4530  }
4531  else
4532  return "failed";

References ESTATUS_DEADLOCK_ERROR, ESTATUS_SERIALIZATION_ERROR, failures_detailed, and pg_fatal.

Referenced by doLog().

◆ getSQLErrorStatus()

static EStatus getSQLErrorStatus ( const char *  sqlState)
static

Definition at line 3206 of file pgbench.c.

3208 {
3209  if (sqlState != NULL)
3210  {
3211  if (strcmp(sqlState, ERRCODE_T_R_SERIALIZATION_FAILURE) == 0)
3213  else if (strcmp(sqlState, ERRCODE_T_R_DEADLOCK_DETECTED) == 0)
3214  return ESTATUS_DEADLOCK_ERROR;
3215  }
3216 
3217  return ESTATUS_OTHER_SQL_ERROR;
#define ERRCODE_T_R_DEADLOCK_DETECTED
Definition: pgbench.c:77
#define ERRCODE_T_R_SERIALIZATION_FAILURE
Definition: pgbench.c:76

References ERRCODE_T_R_DEADLOCK_DETECTED, ERRCODE_T_R_SERIALIZATION_FAILURE, ESTATUS_DEADLOCK_ERROR, ESTATUS_OTHER_SQL_ERROR, and ESTATUS_SERIALIZATION_ERROR.

Referenced by readCommandResponse().

◆ GetTableInfo()

static void GetTableInfo ( PGconn con,
bool  scale_given 
)
static

Definition at line 5306 of file pgbench.c.

5308 {
5309  PGresult *res;
5310 
5311  /*
5312  * get the scaling factor that should be same as count(*) from
5313  * pgbench_branches if this is not a custom query
5314  */
5315  res = PQexec(con, "select count(*) from pgbench_branches");
5317  {
5318  char *sqlState = PQresultErrorField(res, PG_DIAG_SQLSTATE);
5319 
5320  pg_log_error("could not count number of branches: %s", PQerrorMessage(con));
5321 
5322  if (sqlState && strcmp(sqlState, ERRCODE_UNDEFINED_TABLE) == 0)
5323  pg_log_error_hint("Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".",
5324  PQdb(con));
5325 
5326  exit(1);
5327  }
5328  scale = atoi(PQgetvalue(res, 0, 0));
5329  if (scale < 0)
5330  pg_fatal("invalid count(*) from pgbench_branches: \"%s\"",
5331  PQgetvalue(res, 0, 0));
5332  PQclear(res);
5333 
5334  /* warn if we override user-given -s switch */
5335  if (scale_given)
5336  pg_log_warning("scale option ignored, using count from pgbench_branches table (%d)",
5337  scale);
5338 
5339  /*
5340  * Get the partition information for the first "pgbench_accounts" table
5341  * found in search_path.
5342  *
5343  * The result is empty if no "pgbench_accounts" is found.
5344  *
5345  * Otherwise, it always returns one row even if the table is not
5346  * partitioned (in which case the partition strategy is NULL).
5347  *
5348  * The number of partitions can be 0 even for partitioned tables, if no
5349  * partition is attached.
5350  *
5351  * We assume no partitioning on any failure, so as to avoid failing on an
5352  * old version without "pg_partitioned_table".
5353  */
5354  res = PQexec(con,
5355  "select o.n, p.partstrat, pg_catalog.count(i.inhparent) "
5356  "from pg_catalog.pg_class as c "
5357  "join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) "
5358  "cross join lateral (select pg_catalog.array_position(pg_catalog.current_schemas(true), n.nspname)) as o(n) "
5359  "left join pg_catalog.pg_partitioned_table as p on (p.partrelid = c.oid) "
5360  "left join pg_catalog.pg_inherits as i on (c.oid = i.inhparent) "
5361  "where c.relname = 'pgbench_accounts' and o.n is not null "
5362  "group by 1, 2 "
5363  "order by 1 asc "
5364  "limit 1");
5365 
5367  {
5368  /* probably an older version, coldly assume no partitioning */
5370  partitions = 0;
5371  }
5372  else if (PQntuples(res) == 0)
5373  {
5374  /*
5375  * This case is unlikely as pgbench already found "pgbench_branches"
5376  * above to compute the scale.
5377  */
5378  pg_log_error("no pgbench_accounts table found in search_path");
5379  pg_log_error_hint("Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".", PQdb(con));
5380  exit(1);
5381  }
5382  else /* PQntuples(res) == 1 */
5383  {
5384  /* normal case, extract partition information */
5385  if (PQgetisnull(res, 0, 1))
5387  else
5388  {
5389  char *ps = PQgetvalue(res, 0, 1);
5390 
5391  /* column must be there */
5392  Assert(ps != NULL);
5393 
5394  if (strcmp(ps, "r") == 0)
5396  else if (strcmp(ps, "h") == 0)
5398  else
5399  {
5400  /* possibly a newer version with new partition method */
5401  pg_fatal("unexpected partition method: \"%s\"", ps);
5402  }
5403  }
5404 
5405  partitions = atoi(PQgetvalue(res, 0, 2));
5406  }
5407 
5408  PQclear(res);
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:6687
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3441
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3836
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3861
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3426
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:100
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:56

References Assert(), ERRCODE_UNDEFINED_TABLE, exit(), PART_HASH, PART_NONE, PART_RANGE, partition_method, partitions, PG_DIAG_SQLSTATE, pg_fatal, pg_log_error, pg_log_error_hint, pg_log_warning, PGRES_TUPLES_OK, PQclear(), PQdb(), PQerrorMessage(), PQexec(), PQgetisnull(), PQgetvalue(), PQntuples(), PQresultErrorField(), PQresultStatus(), ps, res, and scale.

Referenced by main().

◆ getTransactionStatus()

static TStatus getTransactionStatus ( PGconn con)
static

Definition at line 3512 of file pgbench.c.

3514 {
3515  PGTransactionStatusType tx_status;
3516 
3517  tx_status = PQtransactionStatus(con);
3518  switch (tx_status)
3519  {
3520  case PQTRANS_IDLE:
3521  return TSTATUS_IDLE;
3522  case PQTRANS_INTRANS:
3523  case PQTRANS_INERROR:
3524  return TSTATUS_IN_BLOCK;
3525  case PQTRANS_UNKNOWN:
3526  /* PQTRANS_UNKNOWN is expected given a broken connection */
3527  if (PQstatus(con) == CONNECTION_BAD)
3528  return TSTATUS_CONN_ERROR;
3529  /* fall through */
3530  case PQTRANS_ACTIVE:
3531  default:
3532 
3533  /*
3534  * We cannot find out whether we are in a transaction block or
3535  * not. Internal error which should never occur.
3536  */
3537  pg_log_error("unexpected transaction status %d", tx_status);
3538  return TSTATUS_OTHER_ERROR;
3539  }
3540 
3541  /* not reached */
3542  Assert(false);
3543  return TSTATUS_OTHER_ERROR;
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:6796
PGTransactionStatusType
Definition: libpq-fe.h:117
@ PQTRANS_INTRANS
Definition: libpq-fe.h:120
@ PQTRANS_IDLE
Definition: libpq-fe.h:118
@ PQTRANS_ACTIVE
Definition: libpq-fe.h:119
@ PQTRANS_UNKNOWN
Definition: libpq-fe.h:122
@ PQTRANS_INERROR
Definition: libpq-fe.h:121

References Assert(), CONNECTION_BAD, pg_log_error, PQstatus(), PQTRANS_ACTIVE, PQTRANS_IDLE, PQTRANS_INERROR, PQTRANS_INTRANS, PQTRANS_UNKNOWN, PQtransactionStatus(), TSTATUS_CONN_ERROR, TSTATUS_IDLE, TSTATUS_IN_BLOCK, and TSTATUS_OTHER_ERROR.

Referenced by advanceConnectionState().

◆ getVariable()

static char* getVariable ( Variables variables,
char *  name 
)
static

Definition at line 1629 of file pgbench.c.

1631 {
1632  Variable *var;
1633  char stringform[64];
1634 
1635  var = lookupVariable(variables, name);
1636  if (var == NULL)
1637  return NULL; /* not found */
1638 
1639  if (var->svalue)
1640  return var->svalue; /* we have it in string form */
1641 
1642  /* We need to produce a string equivalent of the value */
1643  Assert(var->value.type != PGBT_NO_VALUE);
1644  if (var->value.type == PGBT_NULL)
1645  snprintf(stringform, sizeof(stringform), "NULL");
1646  else if (var->value.type == PGBT_BOOLEAN)
1647  snprintf(stringform, sizeof(stringform),
1648  "%s", var->value.u.bval ? "true" : "false");
1649  else if (var->value.type == PGBT_INT)
1650  snprintf(stringform, sizeof(stringform),
1651  INT64_FORMAT, var->value.u.ival);
1652  else if (var->value.type == PGBT_DOUBLE)
1653  snprintf(stringform, sizeof(stringform),
1654  "%.*g", DBL_DIG, var->value.u.dval);
1655  else /* internal error, unexpected type */
1656  Assert(0);
1657  var->svalue = pg_strdup(stringform);
1658  return var->svalue;
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
@ PGBT_NO_VALUE
Definition: pgbench.h:36
#define snprintf
Definition: port.h:238
char * svalue
Definition: pgbench.c:324

References Assert(), PgBenchValue::bval, PgBenchValue::dval, INT64_FORMAT, PgBenchValue::ival, lookupVariable(), name, pg_strdup(), PGBT_BOOLEAN, PGBT_DOUBLE, PGBT_INT, PGBT_NO_VALUE, PGBT_NULL, snprintf, Variable::svalue, PgBenchValue::type, PgBenchValue::u, and Variable::value.

Referenced by assignVariables(), evaluateSleep(), getQueryParams(), and runShellCommand().

◆ getZipfianRand()

static int64 getZipfianRand ( pg_prng_state state,
int64  min,
int64  max,
double  s 
)
static

Definition at line 1229 of file pgbench.c.

1231 {
1232  int64 n = max - min + 1;
1233 
1234  /* abort if parameter is invalid */
1236 
1237  return min - 1 + computeIterativeZipfian(state, n, s);
static int64 computeIterativeZipfian(pg_prng_state *state, int64 n, double s)
Definition: pgbench.c:1199

References Assert(), computeIterativeZipfian(), MAX_ZIPFIAN_PARAM, and MIN_ZIPFIAN_PARAM.

Referenced by evalStandardFunc().

◆ handle_sig_alarm()

static void handle_sig_alarm ( SIGNAL_ARGS  )
static

Definition at line 7702 of file pgbench.c.

7704 {
7705  timer_exceeded = true;

References timer_exceeded.

Referenced by setalarm().

◆ initAccount()

static void initAccount ( PQExpBufferData sql,
int64  curr 
)
static

Definition at line 4929 of file pgbench.c.

4931 {
4932  /* "filler" column defaults to blank padded empty string */
4933  printfPQExpBuffer(sql,
4934  INT64_FORMAT "\t" INT64_FORMAT "\t0\t\n",
4935  curr + 1, curr / naccounts + 1);

References INT64_FORMAT, naccounts, and printfPQExpBuffer().

Referenced by initGenerateDataClientSide().

◆ initBranch()

static void initBranch ( PQExpBufferData sql,
int64  curr 
)
static

Definition at line 4911 of file pgbench.c.

4913 {
4914  /* "filler" column uses NULL */
4915  printfPQExpBuffer(sql,
4916  INT64_FORMAT "\t0\t\\N\n",
4917  curr + 1);

References INT64_FORMAT, and printfPQExpBuffer().

Referenced by initGenerateDataClientSide().

◆ initCreateFKeys()

static void initCreateFKeys ( PGconn con)
static

Definition at line 5175 of file pgbench.c.

5177 {
5178  static const char *const DDLKEYs[] = {
5179  "alter table pgbench_tellers add constraint pgbench_tellers_bid_fkey foreign key (bid) references pgbench_branches",
5180  "alter table pgbench_accounts add constraint pgbench_accounts_bid_fkey foreign key (bid) references pgbench_branches",
5181  "alter table pgbench_history add constraint pgbench_history_bid_fkey foreign key (bid) references pgbench_branches",
5182  "alter table pgbench_history add constraint pgbench_history_tid_fkey foreign key (tid) references pgbench_tellers",
5183  "alter table pgbench_history add constraint pgbench_history_aid_fkey foreign key (aid) references pgbench_accounts"
5184  };
5185  int i;
5186 
5187  fprintf(stderr, "creating foreign keys...\n");
5188  for (i = 0; i < lengthof(DDLKEYs); i++)
5189  {
5190  executeStatement(con, DDLKEYs[i]);
5191  }

References executeStatement(), fprintf, i, and lengthof.

Referenced by runInitSteps().

◆ initCreatePKeys()

static void initCreatePKeys ( PGconn con)
static

Definition at line 5137 of file pgbench.c.

5139 {
5140  static const char *const DDLINDEXes[] = {
5141  "alter table pgbench_branches add primary key (bid)",
5142  "alter table pgbench_tellers add primary key (tid)",
5143  "alter table pgbench_accounts add primary key (aid)"
5144  };
5145  int i;
5146  PQExpBufferData query;
5147 
5148  fprintf(stderr, "creating primary keys...\n");
5149  initPQExpBuffer(&query);
5150 
5151  for (i = 0; i < lengthof(DDLINDEXes); i++)
5152  {
5153  resetPQExpBuffer(&query);
5154  appendPQExpBufferStr(&query, DDLINDEXes[i]);
5155 
5156  if (index_tablespace != NULL)
5157  {
5158  char *escape_tablespace;
5159 
5160  escape_tablespace = PQescapeIdentifier(con, index_tablespace,
5161  strlen(index_tablespace));
5162  appendPQExpBuffer(&query, " using index tablespace %s", escape_tablespace);
5163  PQfreemem(escape_tablespace);
5164  }
5165 
5166  executeStatement(con, query.data);
5167  }
5168 
5169  termPQExpBuffer(&query);
void PQfreemem(void *ptr)
Definition: fe-exec.c:3992
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
Definition: fe-exec.c:4270
char * index_tablespace
Definition: pgbench.c:217
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:146

References appendPQExpBuffer(), appendPQExpBufferStr(), PQExpBufferData::data, executeStatement(), fprintf, i, index_tablespace, initPQExpBuffer(), lengthof, PQescapeIdentifier(), PQfreemem(), resetPQExpBuffer(), and termPQExpBuffer().

Referenced by runInitSteps().

◆ initCreateTables()

static void initCreateTables ( PGconn con)
static

Definition at line 4806 of file pgbench.c.

4808 {
4809  /*
4810  * Note: TPC-B requires at least 100 bytes per row, and the "filler"
4811  * fields in these table declarations were intended to comply with that.
4812  * The pgbench_accounts table complies with that because the "filler"
4813  * column is set to blank-padded empty string. But for all other tables
4814  * the columns default to NULL and so don't actually take any space. We
4815  * could fix that by giving them non-null default values. However, that
4816  * would completely break comparability of pgbench results with prior
4817  * versions. Since pgbench has never pretended to be fully TPC-B compliant
4818  * anyway, we stick with the historical behavior.
4819  */
4820  struct ddlinfo
4821  {
4822  const char *table; /* table name */
4823  const char *smcols; /* column decls if accountIDs are 32 bits */
4824  const char *bigcols; /* column decls if accountIDs are 64 bits */
4825  int declare_fillfactor;
4826  };
4827  static const struct ddlinfo DDLs[] = {
4828  {
4829  "pgbench_history",
4830  "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
4831  "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)",
4832  0
4833  },
4834  {
4835  "pgbench_tellers",
4836  "tid int not null,bid int,tbalance int,filler char(84)",
4837  "tid int not null,bid int,tbalance int,filler char(84)",
4838  1
4839  },
4840  {
4841  "pgbench_accounts",
4842  "aid int not null,bid int,abalance int,filler char(84)",
4843  "aid bigint not null,bid int,abalance int,filler char(84)",
4844  1
4845  },
4846  {
4847  "pgbench_branches",
4848  "bid int not null,bbalance int,filler char(88)",
4849  "bid int not null,bbalance int,filler char(88)",
4850  1
4851  }
4852  };
4853  int i;
4854  PQExpBufferData query;
4855 
4856  fprintf(stderr, "creating tables...\n");
4857 
4858  initPQExpBuffer(&query);
4859 
4860  for (i = 0; i < lengthof(DDLs); i++)
4861  {
4862  const struct ddlinfo *ddl = &DDLs[i];
4863 
4864  /* Construct new create table statement. */
4865  printfPQExpBuffer(&query, "create%s table %s(%s)",
4866  unlogged_tables ? " unlogged" : "",
4867  ddl->table,
4868  (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols);
4869 
4870  /* Partition pgbench_accounts table */
4871  if (partition_method != PART_NONE && strcmp(ddl->table, "pgbench_accounts") == 0)
4872  appendPQExpBuffer(&query,
4873  " partition by %s (aid)", PARTITION_METHOD[partition_method]);
4874  else if (ddl->declare_fillfactor)
4875  {
4876  /* fillfactor is only expected on actual tables */
4877  appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
4878  }
4879 
4880  if (tablespace != NULL)
4881  {
4882  char *escape_tablespace;
4883 
4884  escape_tablespace = PQescapeIdentifier(con, tablespace, strlen(tablespace));
4885  appendPQExpBuffer(&query, " tablespace %s", escape_tablespace);
4886  PQfreemem(escape_tablespace);
4887  }
4888 
4889  executeStatement(con, query.data);
4890  }
4891 
4892  termPQExpBuffer(&query);
4893 
4894  if (partition_method != PART_NONE)
4895  createPartitions(con);
static void createPartitions(PGconn *con)
Definition: pgbench.c:4737
static const char *const PARTITION_METHOD[]
Definition: pgbench.c:234
#define SCALE_32BIT_THRESHOLD
Definition: pgbench.c:254
char * tablespace
Definition: pgbench.c:216

References appendPQExpBuffer(), createPartitions(), PQExpBufferData::data, executeStatement(), fillfactor, fprintf, i, initPQExpBuffer(), lengthof, PART_NONE, partition_method, PARTITION_METHOD, PQescapeIdentifier(), PQfreemem(), printfPQExpBuffer(), scale, SCALE_32BIT_THRESHOLD, tablespace, termPQExpBuffer(), and unlogged_tables.

Referenced by runInitSteps().

◆ initDropTables()

static void initDropTables ( PGconn con)
static

Definition at line 4715 of file pgbench.c.

4717 {
4718  fprintf(stderr, "dropping old tables...\n");
4719 
4720  /*
4721  * We drop all the tables in one command, so that whether there are
4722  * foreign key dependencies or not doesn't matter.
4723  */
4724  executeStatement(con, "drop table if exists "
4725  "pgbench_accounts, "
4726  "pgbench_branches, "
4727  "pgbench_history, "
4728  "pgbench_tellers");

References executeStatement(), and fprintf.

Referenced by runInitSteps().

◆ initGenerateDataClientSide()

static void initGenerateDataClientSide ( PGconn con)
static

Definition at line 5047 of file pgbench.c.

5049 {
5050  fprintf(stderr, "generating data (client-side)...\n");
5051 
5052  /*
5053  * we do all of this in one transaction to enable the backend's
5054  * data-loading optimizations
5055  */
5056  executeStatement(con, "begin");
5057 
5058  /* truncate away any old data */
5059  initTruncateTables(con);
5060 
5061  /*
5062  * fill branches, tellers, accounts in that order in case foreign keys
5063  * already exist
5064  */
5065  initPopulateTable(con, "pgbench_branches", nbranches, initBranch);
5066  initPopulateTable(con, "pgbench_tellers", ntellers, initTeller);
5067  initPopulateTable(con, "pgbench_accounts", naccounts, initAccount);
5068 
5069  executeStatement(con, "commit");
static void initTeller(PQExpBufferData *sql, int64 curr)
Definition: pgbench.c:4920
static void initBranch(PQExpBufferData *sql, int64 curr)
Definition: pgbench.c:4911
#define ntellers
Definition: pgbench.c:244
static void initTruncateTables(PGconn *con)
Definition: pgbench.c:4901
static void initAccount(PQExpBufferData *sql, int64 curr)
Definition: pgbench.c:4929
#define nbranches
Definition: pgbench.c:243
static void initPopulateTable(PGconn *con, const char *table, int64 base, initRowMethod init_row)
Definition: pgbench.c:4938

References executeStatement(), fprintf, initAccount(), initBranch(), initPopulateTable(), initTeller(), initTruncateTables(), naccounts, nbranches, and ntellers.

Referenced by runInitSteps().

◆ initGenerateDataServerSide()

static void initGenerateDataServerSide ( PGconn con)
static

Definition at line 5079 of file pgbench.c.

5081 {
5082  PQExpBufferData sql;
5083 
5084  fprintf(stderr, "generating data (server-side)...\n");
5085 
5086  /*
5087  * we do all of this in one transaction to enable the backend's
5088  * data-loading optimizations
5089  */
5090  executeStatement(con, "begin");
5091 
5092  /* truncate away any old data */
5093  initTruncateTables(con);
5094