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 "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 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   void *
 
#define THREAD_FUNC_RETURN_TYPE   void *
 
#define THREAD_FUNC_RETURN   return NULL
 
#define THREAD_FUNC_CC
 
#define THREAD_BARRIER_T   int
 
#define THREAD_BARRIER_INIT(barrier, n)   (*(barrier) = 0)
 
#define THREAD_BARRIER_WAIT(barrier)
 
#define THREAD_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 MAX_PREPARE_NAME   32
 
#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
 

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_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 preparedStatementName (char *buffer, int file, int state)
 
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 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 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 * 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 bool 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 * 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 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 176 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 175 of file pgbench.c.

◆ DEFAULT_NXACTS

#define DEFAULT_NXACTS   10 /* default nxacts */

Definition at line 179 of file pgbench.c.

◆ ERRCODE_T_R_DEADLOCK_DETECTED

#define ERRCODE_T_R_DEADLOCK_DETECTED   "40P01"

Definition at line 80 of file pgbench.c.

◆ ERRCODE_T_R_SERIALIZATION_FAILURE

#define ERRCODE_T_R_SERIALIZATION_FAILURE   "40001"

Definition at line 79 of file pgbench.c.

◆ ERRCODE_UNDEFINED_TABLE

#define ERRCODE_UNDEFINED_TABLE   "42P01"

Definition at line 81 of file pgbench.c.

◆ FNV_OFFSET_BASIS

#define FNV_OFFSET_BASIS   UINT64CONST(0xcbf29ce484222325)

Definition at line 87 of file pgbench.c.

◆ FNV_PRIME

#define FNV_PRIME   UINT64CONST(0x100000001b3)

Definition at line 86 of file pgbench.c.

◆ LOG_STEP_SECONDS

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

Definition at line 178 of file pgbench.c.

◆ M_PI

#define M_PI   3.14159265358979323846

Definition at line 76 of file pgbench.c.

◆ MAX_ARGS

#define MAX_ARGS   256

Definition at line 695 of file pgbench.c.

◆ MAX_FARGS

#define MAX_FARGS   16

Definition at line 2256 of file pgbench.c.

◆ MAX_PREPARE_NAME

#define MAX_PREPARE_NAME   32

Definition at line 3029 of file pgbench.c.

◆ MAX_SCRIPTS

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

Definition at line 359 of file pgbench.c.

◆ MAX_ZIPFIAN_PARAM

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

Definition at line 184 of file pgbench.c.

◆ META_COMMAND

#define META_COMMAND   2

Definition at line 689 of file pgbench.c.

◆ MIN_GAUSSIAN_PARAM

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

Definition at line 181 of file pgbench.c.

◆ MIN_ZIPFIAN_PARAM

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

Definition at line 183 of file pgbench.c.

◆ MM2_MUL

#define MM2_MUL   UINT64CONST(0xc6a4a7935bd1e995)

Definition at line 88 of file pgbench.c.

◆ MM2_MUL_TIMES_8

#define MM2_MUL_TIMES_8   UINT64CONST(0x35253c9ade8f4ca8)

Definition at line 89 of file pgbench.c.

◆ MM2_ROT

#define MM2_ROT   47

Definition at line 90 of file pgbench.c.

◆ naccounts

#define naccounts   100000

Definition at line 258 of file pgbench.c.

◆ nbranches

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

Definition at line 256 of file pgbench.c.

◆ ntellers

#define ntellers   10

Definition at line 257 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 870 of file pgbench.c.

◆ POLL_USING_SELECT

#define POLL_USING_SELECT

Definition at line 54 of file pgbench.c.

◆ SCALE_32BIT_THRESHOLD

#define SCALE_32BIT_THRESHOLD   20000

Definition at line 267 of file pgbench.c.

◆ SHELL_COMMAND_SIZE

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

Definition at line 360 of file pgbench.c.

◆ SOCKET_WAIT_METHOD

#define SOCKET_WAIT_METHOD   "select"

Definition at line 109 of file pgbench.c.

◆ SQL_COMMAND

#define SQL_COMMAND   1

Definition at line 688 of file pgbench.c.

◆ THREAD_BARRIER_DESTROY

#define THREAD_BARRIER_DESTROY (   barrier)

Definition at line 168 of file pgbench.c.

◆ THREAD_BARRIER_INIT

#define THREAD_BARRIER_INIT (   barrier,
 
)    (*(barrier) = 0)

Definition at line 166 of file pgbench.c.

◆ THREAD_BARRIER_T

#define THREAD_BARRIER_T   int

Definition at line 165 of file pgbench.c.

◆ THREAD_BARRIER_WAIT

#define THREAD_BARRIER_WAIT (   barrier)

Definition at line 167 of file pgbench.c.

◆ THREAD_FUNC_CC

#define THREAD_FUNC_CC

Definition at line 164 of file pgbench.c.

◆ THREAD_FUNC_RETURN

#define THREAD_FUNC_RETURN   return NULL

Definition at line 163 of file pgbench.c.

◆ THREAD_FUNC_RETURN_TYPE

#define THREAD_FUNC_RETURN_TYPE   void *

Definition at line 162 of file pgbench.c.

◆ THREAD_T

#define THREAD_T   void *

Definition at line 161 of file pgbench.c.

◆ VARIABLES_ALLOC_MARGIN

#define VARIABLES_ALLOC_MARGIN   8

Definition at line 322 of file pgbench.c.

◆ WSEP

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

Definition at line 314 of file pgbench.c.

Typedef Documentation

◆ BuiltinScript

typedef struct BuiltinScript BuiltinScript

◆ Command

typedef struct Command Command

◆ EStatus

typedef enum EStatus EStatus

◆ MetaCommand

typedef enum MetaCommand MetaCommand

◆ ParsedScript

typedef struct ParsedScript ParsedScript

◆ pg_time_usec_t

typedef int64 pg_time_usec_t

Definition at line 382 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 497 of file pgbench.c.

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

◆ EStatus

enum EStatus
Enumerator
ESTATUS_NO_ERROR 
ESTATUS_META_COMMAND_ERROR 
ESTATUS_SERIALIZATION_ERROR 
ESTATUS_DEADLOCK_ERROR 
ESTATUS_OTHER_SQL_ERROR 

Definition at line 466 of file pgbench.c.

468 {
469  ESTATUS_NO_ERROR = 0,
471 
472  /* SQL errors */
@ ESTATUS_DEADLOCK_ERROR
Definition: pgbench.c:473
@ ESTATUS_META_COMMAND_ERROR
Definition: pgbench.c:469
@ ESTATUS_OTHER_SQL_ERROR
Definition: pgbench.c:474
@ ESTATUS_NO_ERROR
Definition: pgbench.c:468
@ ESTATUS_SERIALIZATION_ERROR
Definition: pgbench.c:472

◆ 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_ENDPIPELINE 

Definition at line 697 of file pgbench.c.

699 {
700  META_NONE, /* not a known meta-command */
701  META_SET, /* \set */
702  META_SETSHELL, /* \setshell */
703  META_SHELL, /* \shell */
704  META_SLEEP, /* \sleep */
705  META_GSET, /* \gset */
706  META_ASET, /* \aset */
707  META_IF, /* \if */
708  META_ELIF, /* \elif */
709  META_ELSE, /* \else */
710  META_ENDIF, /* \endif */
711  META_STARTPIPELINE, /* \startpipeline */
712  META_ENDPIPELINE /* \endpipeline */
@ META_ELSE
Definition: pgbench.c:708
@ META_SETSHELL
Definition: pgbench.c:701
@ META_ENDIF
Definition: pgbench.c:709
@ META_SHELL
Definition: pgbench.c:702
@ META_STARTPIPELINE
Definition: pgbench.c:710
@ META_SET
Definition: pgbench.c:700
@ META_ELIF
Definition: pgbench.c:707
@ META_SLEEP
Definition: pgbench.c:703
@ META_NONE
Definition: pgbench.c:699
@ META_IF
Definition: pgbench.c:706
@ META_ENDPIPELINE
Definition: pgbench.c:711
@ META_ASET
Definition: pgbench.c:705
@ META_GSET
Definition: pgbench.c:704

◆ partition_method_t

Enumerator
PART_NONE 
PART_RANGE 
PART_HASH 

Definition at line 239 of file pgbench.c.

240 {
241  PART_NONE, /* no partitioning */
242  PART_RANGE, /* range partitioning */
243  PART_HASH /* hash partitioning */
partition_method_t
Definition: pgbench.c:240
@ PART_NONE
Definition: pgbench.c:241
@ PART_RANGE
Definition: pgbench.c:242
@ PART_HASH
Definition: pgbench.c:243

◆ QueryMode

enum QueryMode
Enumerator
QUERY_SIMPLE 
QUERY_EXTENDED 
QUERY_PREPARED 
NUM_QUERYMODE 

Definition at line 714 of file pgbench.c.

716 {
717  QUERY_SIMPLE, /* simple query */
718  QUERY_EXTENDED, /* extended query */
719  QUERY_PREPARED, /* extended query with prepared statements */
@ QUERY_PREPARED
Definition: pgbench.c:718
@ NUM_QUERYMODE
Definition: pgbench.c:719
@ QUERY_SIMPLE
Definition: pgbench.c:716
@ QUERY_EXTENDED
Definition: pgbench.c:717

◆ TStatus

enum TStatus
Enumerator
TSTATUS_IDLE 
TSTATUS_IN_BLOCK 
TSTATUS_CONN_ERROR 
TSTATUS_OTHER_ERROR 

Definition at line 480 of file pgbench.c.

482 {
483  TSTATUS_IDLE,
@ TSTATUS_CONN_ERROR
Definition: pgbench.c:484
@ TSTATUS_IDLE
Definition: pgbench.c:482
@ TSTATUS_IN_BLOCK
Definition: pgbench.c:483
@ TSTATUS_OTHER_ERROR
Definition: pgbench.c:485

Function Documentation

◆ accumStats()

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

Definition at line 1463 of file pgbench.c.

1466 {
1467  /* Record the skipped transaction */
1468  if (skipped)
1469  {
1470  /* no latency to record on skipped transactions */
1471  stats->skipped++;
1472  return;
1473  }
1474 
1475  /*
1476  * Record the number of retries regardless of whether the transaction was
1477  * successful or failed.
1478  */
1479  if (tries > 1)
1480  {
1481  stats->retries += (tries - 1);
1482  stats->retried++;
1483  }
1484 
1485  switch (estatus)
1486  {
1487  /* Record the successful transaction */
1488  case ESTATUS_NO_ERROR:
1489  stats->cnt++;
1490 
1491  addToSimpleStats(&stats->latency, lat);
1492 
1493  /* and possibly the same for schedule lag */
1494  if (throttle_delay)
1495  addToSimpleStats(&stats->lag, lag);
1496  break;
1497 
1498  /* Record the failed transaction */
1500  stats->serialization_failures++;
1501  break;
1503  stats->deadlock_failures++;
1504  break;
1505  default:
1506  /* internal error which should never occur */
1507  pg_fatal("unexpected error status: %d", estatus);
1508  }
#define pg_fatal(...)
double throttle_delay
Definition: pgbench.c:216
static void addToSimpleStats(SimpleStats *ss, double val)
Definition: pgbench.c:1415
int64 serialization_failures
Definition: pgbench.c:447
int64 cnt
Definition: pgbench.c:437
int64 retried
Definition: pgbench.c:443
int64 deadlock_failures
Definition: pgbench.c:450
int64 skipped
Definition: pgbench.c:439
SimpleStats lag
Definition: pgbench.c:454
int64 retries
Definition: pgbench.c:441
SimpleStats latency
Definition: pgbench.c:453

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 7752 of file pgbench.c.

7754 {
7755  if (fd < 0 || fd >= FD_SETSIZE)
7756  {
7757  /*
7758  * Doing a hard exit here is a bit grotty, but it doesn't seem worth
7759  * complicating the API to make it less grotty.
7760  */
7761  pg_fatal("too many client connections for select()");
7762  }
7763  FD_SET(fd, &sa->fds);
7764  if (fd > sa->maxfd)
7765  sa->maxfd = fd;
static int fd(const char *x, int i)
Definition: preproc-init.c:105

References fd(), and pg_fatal.

Referenced by threadRun().

◆ addScript()

static void addScript ( const ParsedScript script)
static

Definition at line 6087 of file pgbench.c.

6089 {
6090  if (script->commands == NULL || script->commands[0] == NULL)
6091  pg_fatal("empty command list for script \"%s\"", script->desc);
6092 
6093  if (num_scripts >= MAX_SCRIPTS)
6094  pg_fatal("at most %d SQL scripts are allowed", MAX_SCRIPTS);
6095 
6096  CheckConditional(script);
6097 
6098  sql_script[num_scripts] = *script;
6099  num_scripts++;
static void CheckConditional(const ParsedScript *ps)
Definition: pgbench.c:5749
#define MAX_SCRIPTS
Definition: pgbench.c:359
static ParsedScript sql_script[MAX_SCRIPTS]
Definition: pgbench.c:771
static int num_scripts
Definition: pgbench.c:772
const char * desc
Definition: pgbench.c:765
Command ** commands
Definition: pgbench.c:767

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 1415 of file pgbench.c.

1417 {
1418  if (ss->count == 0 || val < ss->min)
1419  ss->min = val;
1420  if (ss->count == 0 || val > ss->max)
1421  ss->max = val;
1422  ss->count++;
1423  ss->sum += val;
1424  ss->sum2 += val * val;
long val
Definition: informix.c:664
int64 count
Definition: pgbench.c:370
double sum
Definition: pgbench.c:373
double min
Definition: pgbench.c:371
double max
Definition: pgbench.c:372
double sum2
Definition: pgbench.c:374

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 3548 of file pgbench.c.

3550 {
3551 
3552  /*
3553  * gettimeofday() isn't free, so we get the current timestamp lazily the
3554  * first time it's needed, and reuse the same value throughout this
3555  * function after that. This also ensures that e.g. the calculated
3556  * latency reported in the log file and in the totals are the same. Zero
3557  * means "not set yet". Reset "now" when we execute shell commands or
3558  * expressions, which might take a non-negligible amount of time, though.
3559  */
3560  pg_time_usec_t now = 0;
3561 
3562  /*
3563  * Loop in the state machine, until we have to wait for a result from the
3564  * server or have to sleep for throttling or \sleep.
3565  *
3566  * Note: In the switch-statement below, 'break' will loop back here,
3567  * meaning "continue in the state machine". Return is used to return to
3568  * the caller, giving the thread the opportunity to advance another
3569  * client.
3570  */
3571  for (;;)
3572  {
3573  Command *command;
3574 
3575  switch (st->state)
3576  {
3577  /* Select transaction (script) to run. */
3578  case CSTATE_CHOOSE_SCRIPT:
3579  st->use_file = chooseScript(thread);
3581 
3582  /* reset transaction variables to default values */
3583  st->estatus = ESTATUS_NO_ERROR;
3584  st->tries = 1;
3585 
3586  pg_log_debug("client %d executing script \"%s\"",
3587  st->id, sql_script[st->use_file].desc);
3588 
3589  /*
3590  * If time is over, we're done; otherwise, get ready to start
3591  * a new transaction, or to get throttled if that's requested.
3592  */
3595  break;
3596 
3597  /* Start new transaction (script) */
3598  case CSTATE_START_TX:
3600 
3601  /* establish connection if needed, i.e. under --connect */
3602  if (st->con == NULL)
3603  {
3604  pg_time_usec_t start = now;
3605 
3606  if ((st->con = doConnect()) == NULL)
3607  {
3608  /*
3609  * as the bench is already running, we do not abort
3610  * the process
3611  */
3612  pg_log_error("client %d aborted while establishing connection", st->id);
3613  st->state = CSTATE_ABORTED;
3614  break;
3615  }
3616 
3617  /* reset now after connection */
3618  now = pg_time_now();
3619 
3620  thread->conn_duration += now - start;
3621 
3622  /* Reset session-local state */
3623  memset(st->prepared, 0, sizeof(st->prepared));
3624  }
3625 
3626  /*
3627  * It is the first try to run this transaction. Remember the
3628  * random state: maybe it will get an error and we will need
3629  * to run it again.
3630  */
3631  st->random_state = st->cs_func_rs;
3632 
3633  /* record transaction start time */
3634  st->txn_begin = now;
3635 
3636  /*
3637  * When not throttling, this is also the transaction's
3638  * scheduled start time.
3639  */
3640  if (!throttle_delay)
3641  st->txn_scheduled = now;
3642 
3643  /* Begin with the first command */
3645  st->command = 0;
3646  break;
3647 
3648  /*
3649  * Handle throttling once per transaction by sleeping.
3650  */
3652 
3653  /*
3654  * Generate a delay such that the series of delays will
3655  * approximate a Poisson distribution centered on the
3656  * throttle_delay time.
3657  *
3658  * If transactions are too slow or a given wait is shorter
3659  * than a transaction, the next transaction will start right
3660  * away.
3661  */
3662  Assert(throttle_delay > 0);
3663 
3664  thread->throttle_trigger +=
3666  st->txn_scheduled = thread->throttle_trigger;
3667 
3668  /*
3669  * If --latency-limit is used, and this slot is already late
3670  * so that the transaction will miss the latency limit even if
3671  * it completed immediately, skip this time slot and loop to
3672  * reschedule.
3673  */
3674  if (latency_limit)
3675  {
3677 
3678  if (thread->throttle_trigger < now - latency_limit)
3679  {
3680  processXactStats(thread, st, &now, true, agg);
3681 
3682  /*
3683  * Finish client if -T or -t was exceeded.
3684  *
3685  * Stop counting skipped transactions under -T as soon
3686  * as the timer is exceeded. Because otherwise it can
3687  * take a very long time to count all of them
3688  * especially when quite a lot of them happen with
3689  * unrealistically high rate setting in -R, which
3690  * would prevent pgbench from ending immediately.
3691  * Because of this behavior, note that there is no
3692  * guarantee that all skipped transactions are counted
3693  * under -T though there is under -t. This is OK in
3694  * practice because it's very unlikely to happen with
3695  * realistic setting.
3696  */
3697  if (timer_exceeded || (nxacts > 0 && st->cnt >= nxacts))
3698  st->state = CSTATE_FINISHED;
3699 
3700  /* Go back to top of loop with CSTATE_PREPARE_THROTTLE */
3701  break;
3702  }
3703  }
3704 
3705  /*
3706  * stop client if next transaction is beyond pgbench end of
3707  * execution; otherwise, throttle it.
3708  */
3709  st->state = end_time > 0 && st->txn_scheduled > end_time ?
3711  break;
3712 
3713  /*
3714  * Wait until it's time to start next transaction.
3715  */
3716  case CSTATE_THROTTLE:
3718 
3719  if (now < st->txn_scheduled)
3720  return; /* still sleeping, nothing to do here */
3721 
3722  /* done sleeping, but don't start transaction if we're done */
3724  break;
3725 
3726  /*
3727  * Send a command to server (or execute a meta-command)
3728  */
3729  case CSTATE_START_COMMAND:
3730  command = sql_script[st->use_file].commands[st->command];
3731 
3732  /* Transition to script end processing if done */
3733  if (command == NULL)
3734  {
3735  st->state = CSTATE_END_TX;
3736  break;
3737  }
3738 
3739  /* record begin time of next command, and initiate it */
3740  if (report_per_command)
3741  {
3743  st->stmt_begin = now;
3744  }
3745 
3746  /* Execute the command */
3747  if (command->type == SQL_COMMAND)
3748  {
3749  /* disallow \aset and \gset in pipeline mode */
3750  if (PQpipelineStatus(st->con) != PQ_PIPELINE_OFF)
3751  {
3752  if (command->meta == META_GSET)
3753  {
3754  commandFailed(st, "gset", "\\gset is not allowed in pipeline mode");
3755  st->state = CSTATE_ABORTED;
3756  break;
3757  }
3758  else if (command->meta == META_ASET)
3759  {
3760  commandFailed(st, "aset", "\\aset is not allowed in pipeline mode");
3761  st->state = CSTATE_ABORTED;
3762  break;
3763  }
3764  }
3765 
3766  if (!sendCommand(st, command))
3767  {
3768  commandFailed(st, "SQL", "SQL command send failed");
3769  st->state = CSTATE_ABORTED;
3770  }
3771  else
3772  {
3773  /* Wait for results, unless in pipeline mode */
3774  if (PQpipelineStatus(st->con) == PQ_PIPELINE_OFF)
3775  st->state = CSTATE_WAIT_RESULT;
3776  else
3777  st->state = CSTATE_END_COMMAND;
3778  }
3779  }
3780  else if (command->type == META_COMMAND)
3781  {
3782  /*-----
3783  * Possible state changes when executing meta commands:
3784  * - on errors CSTATE_ABORTED
3785  * - on sleep CSTATE_SLEEP
3786  * - else CSTATE_END_COMMAND
3787  */
3788  st->state = executeMetaCommand(st, &now);
3789  if (st->state == CSTATE_ABORTED)
3791  }
3792 
3793  /*
3794  * We're now waiting for an SQL command to complete, or
3795  * finished processing a metacommand, or need to sleep, or
3796  * something bad happened.
3797  */
3798  Assert(st->state == CSTATE_WAIT_RESULT ||
3799  st->state == CSTATE_END_COMMAND ||
3800  st->state == CSTATE_SLEEP ||
3801  st->state == CSTATE_ABORTED);
3802  break;
3803 
3804  /*
3805  * non executed conditional branch
3806  */
3807  case CSTATE_SKIP_COMMAND:
3809  /* quickly skip commands until something to do... */
3810  while (true)
3811  {
3812  Command *command;
3813 
3814  command = sql_script[st->use_file].commands[st->command];
3815 
3816  /* cannot reach end of script in that state */
3817  Assert(command != NULL);
3818 
3819  /*
3820  * if this is conditional related, update conditional
3821  * state
3822  */
3823  if (command->type == META_COMMAND &&
3824  (command->meta == META_IF ||
3825  command->meta == META_ELIF ||
3826  command->meta == META_ELSE ||
3827  command->meta == META_ENDIF))
3828  {
3829  switch (conditional_stack_peek(st->cstack))
3830  {
3831  case IFSTATE_FALSE:
3832  if (command->meta == META_IF ||
3833  command->meta == META_ELIF)
3834  {
3835  /* we must evaluate the condition */
3837  }
3838  else if (command->meta == META_ELSE)
3839  {
3840  /* we must execute next command */
3844  st->command++;
3845  }
3846  else if (command->meta == META_ENDIF)
3847  {
3850  if (conditional_active(st->cstack))
3852 
3853  /*
3854  * else state remains in
3855  * CSTATE_SKIP_COMMAND
3856  */
3857  st->command++;
3858  }
3859  break;
3860 
3861  case IFSTATE_IGNORED:
3862  case IFSTATE_ELSE_FALSE:
3863  if (command->meta == META_IF)
3865  IFSTATE_IGNORED);
3866  else if (command->meta == META_ENDIF)
3867  {
3870  if (conditional_active(st->cstack))
3872  }
3873  /* could detect "else" & "elif" after "else" */
3874  st->command++;
3875  break;
3876 
3877  case IFSTATE_NONE:
3878  case IFSTATE_TRUE:
3879  case IFSTATE_ELSE_TRUE:
3880  default:
3881 
3882  /*
3883  * inconsistent if inactive, unreachable dead
3884  * code
3885  */
3886  Assert(false);
3887  }
3888  }
3889  else
3890  {
3891  /* skip and consider next */
3892  st->command++;
3893  }
3894 
3895  if (st->state != CSTATE_SKIP_COMMAND)
3896  /* out of quick skip command loop */
3897  break;
3898  }
3899  break;
3900 
3901  /*
3902  * Wait for the current SQL command to complete
3903  */
3904  case CSTATE_WAIT_RESULT:
3905  pg_log_debug("client %d receiving", st->id);
3906 
3907  /*
3908  * Only check for new network data if we processed all data
3909  * fetched prior. Otherwise we end up doing a syscall for each
3910  * individual pipelined query, which has a measurable
3911  * performance impact.
3912  */
3913  if (PQisBusy(st->con) && !PQconsumeInput(st->con))
3914  {
3915  /* there's something wrong */
3916  commandFailed(st, "SQL", "perhaps the backend died while processing");
3917  st->state = CSTATE_ABORTED;
3918  break;
3919  }
3920  if (PQisBusy(st->con))
3921  return; /* don't have the whole result yet */
3922 
3923  /* store or discard the query results */
3924  if (readCommandResponse(st,
3927  {
3928  /*
3929  * outside of pipeline mode: stop reading results.
3930  * pipeline mode: continue reading results until an
3931  * end-of-pipeline response.
3932  */
3933  if (PQpipelineStatus(st->con) != PQ_PIPELINE_ON)
3934  st->state = CSTATE_END_COMMAND;
3935  }
3936  else if (canRetryError(st->estatus))
3937  st->state = CSTATE_ERROR;
3938  else
3939  st->state = CSTATE_ABORTED;
3940  break;
3941 
3942  /*
3943  * Wait until sleep is done. This state is entered after a
3944  * \sleep metacommand. The behavior is similar to
3945  * CSTATE_THROTTLE, but proceeds to CSTATE_START_COMMAND
3946  * instead of CSTATE_START_TX.
3947  */
3948  case CSTATE_SLEEP:
3950  if (now < st->sleep_until)
3951  return; /* still sleeping, nothing to do here */
3952  /* Else done sleeping. */
3953  st->state = CSTATE_END_COMMAND;
3954  break;
3955 
3956  /*
3957  * End of command: record stats and proceed to next command.
3958  */
3959  case CSTATE_END_COMMAND:
3960 
3961  /*
3962  * command completed: accumulate per-command execution times
3963  * in thread-local data structure, if per-command latencies
3964  * are requested.
3965  */
3966  if (report_per_command)
3967  {
3968  Command *command;
3969 
3971 
3972  command = sql_script[st->use_file].commands[st->command];
3973  /* XXX could use a mutex here, but we choose not to */
3974  addToSimpleStats(&command->stats,
3976  }
3977 
3978  /* Go ahead with next command, to be executed or skipped */
3979  st->command++;
3980  st->state = conditional_active(st->cstack) ?
3982  break;
3983 
3984  /*
3985  * Clean up after an error.
3986  */
3987  case CSTATE_ERROR:
3988  {
3989  TStatus tstatus;
3990 
3992 
3993  /* Clear the conditional stack */
3995 
3996  /* Read and discard until a sync point in pipeline mode */
3997  if (PQpipelineStatus(st->con) != PQ_PIPELINE_OFF)
3998  {
3999  if (!discardUntilSync(st))
4000  {
4001  st->state = CSTATE_ABORTED;
4002  break;
4003  }
4004  }
4005 
4006  /*
4007  * Check if we have a (failed) transaction block or not,
4008  * and roll it back if any.
4009  */
4010  tstatus = getTransactionStatus(st->con);
4011  if (tstatus == TSTATUS_IN_BLOCK)
4012  {
4013  /* Try to rollback a (failed) transaction block. */
4014  if (!PQsendQuery(st->con, "ROLLBACK"))
4015  {
4016  pg_log_error("client %d aborted: failed to send sql command for rolling back the failed transaction",
4017  st->id);
4018  st->state = CSTATE_ABORTED;
4019  }
4020  else
4022  }
4023  else if (tstatus == TSTATUS_IDLE)
4024  {
4025  /*
4026  * If time is over, we're done; otherwise, check if we
4027  * can retry the error.
4028  */
4031  }
4032  else
4033  {
4034  if (tstatus == TSTATUS_CONN_ERROR)
4035  pg_log_error("perhaps the backend died while processing");
4036 
4037  pg_log_error("client %d aborted while receiving the transaction status", st->id);
4038  st->state = CSTATE_ABORTED;
4039  }
4040  break;
4041  }
4042 
4043  /*
4044  * Wait for the rollback command to complete
4045  */
4047  {
4048  PGresult *res;
4049 
4050  pg_log_debug("client %d receiving", st->id);
4051  if (!PQconsumeInput(st->con))
4052  {
4053  pg_log_error("client %d aborted while rolling back the transaction after an error; perhaps the backend died while processing",
4054  st->id);
4055  st->state = CSTATE_ABORTED;
4056  break;
4057  }
4058  if (PQisBusy(st->con))
4059  return; /* don't have the whole result yet */
4060 
4061  /*
4062  * Read and discard the query result;
4063  */
4064  res = PQgetResult(st->con);
4065  switch (PQresultStatus(res))
4066  {
4067  case PGRES_COMMAND_OK:
4068  /* OK */
4069  PQclear(res);
4070  /* null must be returned */
4071  res = PQgetResult(st->con);
4072  Assert(res == NULL);
4073 
4074  /*
4075  * If time is over, we're done; otherwise, check
4076  * if we can retry the error.
4077  */
4080  break;
4081  default:
4082  pg_log_error("client %d aborted while rolling back the transaction after an error; %s",
4083  st->id, PQerrorMessage(st->con));
4084  PQclear(res);
4085  st->state = CSTATE_ABORTED;
4086  break;
4087  }
4088  break;
4089  }
4090 
4091  /*
4092  * Retry the transaction after an error.
4093  */
4094  case CSTATE_RETRY:
4095  command = sql_script[st->use_file].commands[st->command];
4096 
4097  /*
4098  * Inform that the transaction will be retried after the
4099  * error.
4100  */
4101  if (verbose_errors)
4102  printVerboseErrorMessages(st, &now, true);
4103 
4104  /* Count tries and retries */
4105  st->tries++;
4106  command->retries++;
4107 
4108  /*
4109  * Reset the random state as they were at the beginning of the
4110  * transaction.
4111  */
4112  st->cs_func_rs = st->random_state;
4113 
4114  /* Process the first transaction command. */
4115  st->command = 0;
4116  st->estatus = ESTATUS_NO_ERROR;
4118  break;
4119 
4120  /*
4121  * Record a failed transaction.
4122  */
4123  case CSTATE_FAILURE:
4124  command = sql_script[st->use_file].commands[st->command];
4125 
4126  /* Accumulate the failure. */
4127  command->failures++;
4128 
4129  /*
4130  * Inform that the failed transaction will not be retried.
4131  */
4132  if (verbose_errors)
4133  printVerboseErrorMessages(st, &now, false);
4134 
4135  /* End the failed transaction. */
4136  st->state = CSTATE_END_TX;
4137  break;
4138 
4139  /*
4140  * End of transaction (end of script, really).
4141  */
4142  case CSTATE_END_TX:
4143  {
4144  TStatus tstatus;
4145 
4146  /* transaction finished: calculate latency and do log */
4147  processXactStats(thread, st, &now, false, agg);
4148 
4149  /*
4150  * missing \endif... cannot happen if CheckConditional was
4151  * okay
4152  */
4154 
4155  /*
4156  * We must complete all the transaction blocks that were
4157  * started in this script.
4158  */
4159  tstatus = getTransactionStatus(st->con);
4160  if (tstatus == TSTATUS_IN_BLOCK)
4161  {
4162  pg_log_error("client %d aborted: end of script reached without completing the last transaction",
4163  st->id);
4164  st->state = CSTATE_ABORTED;
4165  break;
4166  }
4167  else if (tstatus != TSTATUS_IDLE)
4168  {
4169  if (tstatus == TSTATUS_CONN_ERROR)
4170  pg_log_error("perhaps the backend died while processing");
4171 
4172  pg_log_error("client %d aborted while receiving the transaction status", st->id);
4173  st->state = CSTATE_ABORTED;
4174  break;
4175  }
4176 
4177  if (is_connect)
4178  {
4179  pg_time_usec_t start = now;
4180 
4181  pg_time_now_lazy(&start);
4182  finishCon(st);
4183  now = pg_time_now();
4184  thread->conn_duration += now - start;
4185  }
4186 
4187  if ((st->cnt >= nxacts && duration <= 0) || timer_exceeded)
4188  {
4189  /* script completed */
4190  st->state = CSTATE_FINISHED;
4191  break;
4192  }
4193 
4194  /* next transaction (script) */
4196 
4197  /*
4198  * Ensure that we always return on this point, so as to
4199  * avoid an infinite loop if the script only contains meta
4200  * commands.
4201  */
4202  return;
4203  }
4204 
4205  /*
4206  * Final states. Close the connection if it's still open.
4207  */
4208  case CSTATE_ABORTED:
4209  case CSTATE_FINISHED:
4210 
4211  /*
4212  * Don't measure the disconnection delays here even if in
4213  * CSTATE_FINISHED and -C/--connect option is specified.
4214  * Because in this case all the connections that this thread
4215  * established are closed at the end of transactions and the
4216  * disconnection delays should have already been measured at
4217  * that moment.
4218  *
4219  * In CSTATE_ABORTED state, the measurement is no longer
4220  * necessary because we cannot report complete results anyways
4221  * in this case.
4222  */
4223  finishCon(st);
4224  return;
4225  }
4226  }
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1538
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:6908
PGpipelineStatus PQpipelineStatus(const PGconn *conn)
Definition: fe-connect.c:6950
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3270
void PQclear(PGresult *res)
Definition: fe-exec.c:718
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:2004
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1424
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2051
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2082
@ 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_error(...)
Definition: logging.h:106
#define pg_log_debug(...)
Definition: logging.h:133
static pg_time_usec_t pg_time_now(void)
Definition: pgbench.c:854
static void printVerboseErrorMessages(CState *st, pg_time_usec_t *now, bool is_retry)
Definition: pgbench.c:3509
int64 latency_limit
Definition: pgbench.c:224
static TStatus getTransactionStatus(PGconn *con)
Definition: pgbench.c:3472
int64 end_time
Definition: pgbench.c:188
static bool doRetry(CState *st, pg_time_usec_t *now)
Definition: pgbench.c:3386
static bool sendCommand(CState *st, Command *command)
Definition: pgbench.c:3078
TStatus
Definition: pgbench.c:481
static void finishCon(CState *st)
Definition: pgbench.c:7568
int64 pg_time_usec_t
Definition: pgbench.c:382
bool is_connect
Definition: pgbench.c:278
int nxacts
Definition: pgbench.c:186
bool report_per_command
Definition: pgbench.c:279
#define PG_TIME_GET_DOUBLE(t)
Definition: pgbench.c:870
static int discardUntilSync(CState *st)
Definition: pgbench.c:3432
static ConnectionStateEnum executeMetaCommand(CState *st, pg_time_usec_t *now)
Definition: pgbench.c:4236
static bool canRetryError(EStatus estatus)
Definition: pgbench.c:3185
static void commandFailed(CState *st, const char *cmd, const char *message)
Definition: pgbench.c:3040
static int chooseScript(TState *thread)
Definition: pgbench.c:3059
#define SQL_COMMAND
Definition: pgbench.c:688
static void processXactStats(TState *thread, CState *st, pg_time_usec_t *now, bool skipped, StatsData *agg)
Definition: pgbench.c:4592
int duration
Definition: pgbench.c:187
static void pg_time_now_lazy(pg_time_usec_t *now)
Definition: pgbench.c:864
static bool verbose_errors
Definition: pgbench.c:775
static int64 getPoissonRand(pg_prng_state *state, double center)
Definition: pgbench.c:1191
static PGconn * doConnect(void)
Definition: pgbench.c:1543
volatile bool timer_exceeded
Definition: pgbench.c:316
#define META_COMMAND
Definition: pgbench.c:689
static bool readCommandResponse(CState *st, MetaCommand meta, char *varprefix)
Definition: pgbench.c:3201
int64 cnt
Definition: pgbench.c:647
int id
Definition: pgbench.c:611
pg_time_usec_t txn_scheduled
Definition: pgbench.c:628
bool prepared[MAX_SCRIPTS]
Definition: pgbench.c:633
pg_time_usec_t stmt_begin
Definition: pgbench.c:631
int command
Definition: pgbench.c:622
int use_file
Definition: pgbench.c:621
ConditionalStack cstack
Definition: pgbench.c:613
pg_prng_state random_state
Definition: pgbench.c:642
pg_time_usec_t txn_begin
Definition: pgbench.c:630
EStatus estatus
Definition: pgbench.c:639
PGconn * con
Definition: pgbench.c:610
pg_prng_state cs_func_rs
Definition: pgbench.c:619
uint32 tries
Definition: pgbench.c:643
ConnectionStateEnum state
Definition: pgbench.c:612
int64 retries
Definition: pgbench.c:759
char * varprefix
Definition: pgbench.c:756
int type
Definition: pgbench.c:752
MetaCommand meta
Definition: pgbench.c:753
SimpleStats stats
Definition: pgbench.c:758
int64 failures
Definition: pgbench.c:760
int64 throttle_trigger
Definition: pgbench.c:671
pg_prng_state ts_throttle_rs
Definition: pgbench.c:668
pg_time_usec_t conn_duration
Definition: pgbench.c:678

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_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 7733 of file pgbench.c.

7735 {
7736  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().

◆ assignVariables()

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

Definition at line 1950 of file pgbench.c.

1952 {
1953  char *p,
1954  *name,
1955  *val;
1956 
1957  p = sql;
1958  while ((p = strchr(p, ':')) != NULL)
1959  {
1960  int eaten;
1961 
1962  name = parseVariable(p, &eaten);
1963  if (name == NULL)
1964  {
1965  while (*p == ':')
1966  {
1967  p++;
1968  }
1969  continue;
1970  }
1971 
1972  val = getVariable(variables, name);
1973  free(name);
1974  if (val == NULL)
1975  {
1976  p++;
1977  continue;
1978  }
1979 
1980  p = replaceVariable(&sql, p, eaten, val);
1981  }
1982 
1983  return sql;
const char * name
Definition: encode.c:561
#define free(a)
Definition: header.h:65
static char * getVariable(Variables *variables, char *name)
Definition: pgbench.c:1643
static char * parseVariable(const char *sql, int *eaten)
Definition: pgbench.c:1903
static char * replaceVariable(char **sql, char *param, int len, char *value)
Definition: pgbench.c:1930

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

Referenced by sendCommand().

◆ canRetryError()

static bool canRetryError ( EStatus  estatus)
static

Definition at line 3185 of file pgbench.c.

3187 {
3188  return (estatus == ESTATUS_SERIALIZATION_ERROR ||
3189  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 5749 of file pgbench.c.

5751 {
5752  /* statically check conditional structure */
5754  int i;
5755 
5756  for (i = 0; ps->commands[i] != NULL; i++)
5757  {
5758  Command *cmd = ps->commands[i];
5759 
5760  if (cmd->type == META_COMMAND)
5761  {
5762  switch (cmd->meta)
5763  {
5764  case META_IF:
5766  break;
5767  case META_ELIF:
5768  if (conditional_stack_empty(cs))
5769  ConditionError(ps->desc, i + 1, "\\elif without matching \\if");
5771  ConditionError(ps->desc, i + 1, "\\elif after \\else");
5772  break;
5773  case META_ELSE:
5774  if (conditional_stack_empty(cs))
5775  ConditionError(ps->desc, i + 1, "\\else without matching \\if");
5777  ConditionError(ps->desc, i + 1, "\\else after \\else");
5779  break;
5780  case META_ENDIF:
5781  if (!conditional_stack_pop(cs))
5782  ConditionError(ps->desc, i + 1, "\\endif without matching \\if");
5783  break;
5784  default:
5785  /* ignore anything else... */
5786  break;
5787  }
5788  }
5789  }
5790  if (!conditional_stack_empty(cs))
5791  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
int i
Definition: isn.c:73
static void ConditionError(const char *desc, int cmdn, const char *msg)
Definition: pgbench.c:5739

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

Referenced by addScript().

◆ checkInitSteps()

static void checkInitSteps ( const char *  initialize_steps)
static

Definition at line 5100 of file pgbench.c.

5102 {
5103  if (initialize_steps[0] == '\0')
5104  pg_fatal("no initialization steps specified");
5105 
5106  for (const char *step = initialize_steps; *step != '\0'; step++)
5107  {
5108  if (strchr(ALL_INIT_STEPS " ", *step) == NULL)
5109  {
5110  pg_log_error("unrecognized initialization step \"%c\"", *step);
5111  pg_log_error_detail("Allowed step characters are: \"" ALL_INIT_STEPS "\".");
5112  exit(1);
5113  }
5114  }
exit(1)
#define pg_log_error_detail(...)
Definition: logging.h:109
#define ALL_INIT_STEPS
Definition: pgbench.c:176

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 3059 of file pgbench.c.

3061 {
3062  int i = 0;
3063  int64 w;
3064 
3065  if (num_scripts == 1)
3066  return 0;
3067 
3068  w = getrand(&thread->ts_choose_rs, 0, total_weight - 1);
3069  do
3070  {
3071  w -= sql_script[i++].weight;
3072  } while (w >= 0);
3073 
3074  return i - 1;
static int64 total_weight
Definition: pgbench.c:773
static int64 getrand(pg_prng_state *state, int64 min, int64 max)
Definition: pgbench.c:1096
int weight
Definition: pgbench.c:766
pg_prng_state ts_choose_rs
Definition: pgbench.c:667

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 7745 of file pgbench.c.

7747 {
7748  FD_ZERO(&sa->fds);
7749  sa->maxfd = -1;

Referenced by threadRun().

◆ coerceToBool()

static bool coerceToBool ( PgBenchValue pval,
bool bval 
)
static

Definition at line 2018 of file pgbench.c.

2020 {
2021  if (pval->type == PGBT_BOOLEAN)
2022  {
2023  *bval = pval->u.bval;
2024  return true;
2025  }
2026  else /* NULL, INT or DOUBLE */
2027  {
2028  pg_log_error("cannot coerce %s to boolean", valueTypeName(pval));
2029  *bval = false; /* suppress uninitialized-variable warnings */
2030  return false;
2031  }
static char * valueTypeName(PgBenchValue *pval)
Definition: pgbench.c:1996
@ PGBT_BOOLEAN
Definition: pgbench.h:40
PgBenchValueType type
Definition: pgbench.h:46
bool bval
Definition: pgbench.h:51
union PgBenchValue::@34 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 2087 of file pgbench.c.

2089 {
2090  if (pval->type == PGBT_DOUBLE)
2091  {
2092  *dval = pval->u.dval;
2093  return true;
2094  }
2095  else if (pval->type == PGBT_INT)
2096  {
2097  *dval = (double) pval->u.ival;
2098  return true;
2099  }
2100  else /* BOOLEAN or NULL */
2101  {
2102  pg_log_error("cannot coerce %s to double", valueTypeName(pval));
2103  return false;
2104  }
@ 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 2059 of file pgbench.c.

2061 {
2062  if (pval->type == PGBT_INT)
2063  {
2064  *ival = pval->u.ival;
2065  return true;
2066  }
2067  else if (pval->type == PGBT_DOUBLE)
2068  {
2069  double dval = rint(pval->u.dval);
2070 
2071  if (isnan(dval) || !FLOAT8_FITS_IN_INT64(dval))
2072  {
2073  pg_log_error("double to int overflow for %f", dval);
2074  return false;
2075  }
2076  *ival = (int64) dval;
2077  return true;
2078  }
2079  else /* BOOLEAN or NULL */
2080  {
2081  pg_log_error("cannot coerce %s to int", valueTypeName(pval));
2082  return false;
2083  }
#define FLOAT8_FITS_IN_INT64(num)
Definition: c.h:1104

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 3050 of file pgbench.c.

3052 {
3054  pg_log_info("client %d got an error in command %d (SQL) of script %d; %s",
3055  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 3040 of file pgbench.c.

3042 {
3043  pg_log_error("client %d aborted in command %d (%s) of script %d; %s",
3044  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 1608 of file pgbench.c.

1610 {
1611  return strcmp(((const Variable *) v1)->name,
1612  ((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 1213 of file pgbench.c.

1215 {
1216  double b = pow(2.0, s - 1.0);
1217  double x,
1218  t,
1219  u,
1220  v;
1221 
1222  /* Ensure n is sane */
1223  if (n <= 1)
1224  return 1;
1225 
1226  while (true)
1227  {
1228  /* random variates */
1229  u = pg_prng_double(state);
1230  v = pg_prng_double(state);
1231 
1232  x = floor(pow(u, -1.0 / (s - 1.0)));
1233 
1234  t = pow(1.0 + 1.0 / x, s - 1.0);
1235  /* reject if too large or out of bound */
1236  if (v * x * (t - 1.0) / (b - 1.0) <= t / b && x <= n)
1237  break;
1238  }
1239  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:226
Definition: regguts.h:318

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 5739 of file pgbench.c.

5741 {
5742  pg_fatal("condition error in script \"%s\" command %d: %s",
5743  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 5446 of file pgbench.c.

5448 {
5449  Command *my_command;
5450  char *p = skip_sql_comments(buf->data);
5451 
5452  if (p == NULL)
5453  return NULL;
5454 
5455  /* Allocate and initialize Command structure */
5456  my_command = (Command *) pg_malloc(sizeof(Command));
5457  initPQExpBuffer(&my_command->lines);
5458  appendPQExpBufferStr(&my_command->lines, p);
5459  my_command->first_line = NULL; /* this is set later */
5460  my_command->type = SQL_COMMAND;
5461  my_command->meta = META_NONE;
5462  my_command->argc = 0;
5463  my_command->retries = 0;
5464  my_command->failures = 0;
5465  memset(my_command->argv, 0, sizeof(my_command->argv));
5466  my_command->varprefix = NULL; /* allocated later, if needed */
5467  my_command->expr = NULL;
5468  initSimpleStats(&my_command->stats);
5469 
5470  return my_command;
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
static char * buf
Definition: pg_test_fsync.c:67
static char * skip_sql_comments(char *sql_command)
Definition: pgbench.c:5411
static void initSimpleStats(SimpleStats *ss)
Definition: pgbench.c:1406
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
PQExpBufferData lines
Definition: pgbench.c:750
PgBenchExpr * expr
Definition: pgbench.c:757
char * argv[MAX_ARGS]
Definition: pgbench.c:755
char * first_line
Definition: pgbench.c:751
int argc
Definition: pgbench.c:754

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::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 4665 of file pgbench.c.

4667 {
4668  PQExpBufferData query;
4669 
4670  /* we must have to create some partitions */
4671  Assert(partitions > 0);
4672 
4673  fprintf(stderr, "creating %d partitions...\n", partitions);
4674 
4675  initPQExpBuffer(&query);
4676 
4677  for (int p = 1; p <= partitions; p++)
4678  {
4680  {
4681  int64 part_size = (naccounts * (int64) scale + partitions - 1) / partitions;
4682 
4683  printfPQExpBuffer(&query,
4684  "create%s table pgbench_accounts_%d\n"
4685  " partition of pgbench_accounts\n"
4686  " for values from (",
4687  unlogged_tables ? " unlogged" : "", p);
4688 
4689  /*
4690  * For RANGE, we use open-ended partitions at the beginning and
4691  * end to allow any valid value for the primary key. Although the
4692  * actual minimum and maximum values can be derived from the
4693  * scale, it is more generic and the performance is better.
4694  */
4695  if (p == 1)
4696  appendPQExpBufferStr(&query, "minvalue");
4697  else
4698  appendPQExpBuffer(&query, INT64_FORMAT, (p - 1) * part_size + 1);
4699 
4700  appendPQExpBufferStr(&query, ") to (");
4701 
4702  if (p < partitions)
4703  appendPQExpBuffer(&query, INT64_FORMAT, p * part_size + 1);
4704  else
4705  appendPQExpBufferStr(&query, "maxvalue");
4706 
4707  appendPQExpBufferChar(&query, ')');
4708  }
4709  else if (partition_method == PART_HASH)
4710  printfPQExpBuffer(&query,
4711  "create%s table pgbench_accounts_%d\n"
4712  " partition of pgbench_accounts\n"
4713  " for values with (modulus %d, remainder %d)",
4714  unlogged_tables ? " unlogged" : "", p,
4715  partitions, p - 1);
4716  else /* cannot get there */
4717  Assert(0);
4718 
4719  /*
4720  * Per ddlinfo in initCreateTables, fillfactor is needed on table
4721  * pgbench_accounts.
4722  */
4723  appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
4724 
4725  executeStatement(con, query.data);
4726  }
4727 
4728  termPQExpBuffer(&query);
#define INT64_FORMAT
Definition: c.h:483
int scale
Definition: pgbench.c:194
static int partitions
Definition: pgbench.c:236
int fillfactor
Definition: pgbench.c:200
static partition_method_t partition_method
Definition: pgbench.c:246
bool unlogged_tables
Definition: pgbench.c:205
#define naccounts
Definition: pgbench.c:258
static void executeStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1512
#define fprintf
Definition: port.h:229
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131

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 3432 of file pgbench.c.

3434 {
3435  /* send a sync */
3436  if (!PQpipelineSync(st->con))
3437  {
3438  pg_log_error("client %d aborted: failed to send a pipeline sync",
3439  st->id);
3440  return 0;
3441  }
3442 
3443  /* receive PGRES_PIPELINE_SYNC and null following it */
3444  for (;;)
3445  {
3446  PGresult *res = PQgetResult(st->con);
3447 
3449  {
3450  PQclear(res);
3451  res = PQgetResult(st->con);
3452  Assert(res == NULL);
3453  break;
3454  }
3455  PQclear(res);
3456  }
3457 
3458  /* exit pipeline */
3459  if (PQexitPipelineMode(st->con) != 1)
3460  {
3461  pg_log_error("client %d aborted: failed to exit pipeline mode for rolling back the failed transaction",
3462  st->id);
3463  return 0;
3464  }
3465  return 1;
int PQexitPipelineMode(PGconn *conn)
Definition: fe-exec.c:3012
int PQpipelineSync(PGconn *conn)
Definition: fe-exec.c:3169
@ 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 4631 of file pgbench.c.

4633 {
4634  int i;
4635 
4636  for (i = 0; i < length; i++)
4637  finishCon(&state[i]);

References finishCon(), and i.

Referenced by main(), and threadRun().

◆ doConnect()

static PGconn* doConnect ( void  )
static

Definition at line 1543 of file pgbench.c.

1545 {
1546  PGconn *conn;
1547  bool new_pass;
1548  static char *password = NULL;
1549 
1550  /*
1551  * Start the connection. Loop until we have a password if requested by
1552  * backend.
1553  */
1554  do
1555  {
1556 #define PARAMS_ARRAY_SIZE 7
1557 
1558  const char *keywords[PARAMS_ARRAY_SIZE];
1559  const char *values[PARAMS_ARRAY_SIZE];
1560 
1561  keywords[0] = "host";
1562  values[0] = pghost;
1563  keywords[1] = "port";
1564  values[1] = pgport;
1565  keywords[2] = "user";
1566  values[2] = username;
1567  keywords[3] = "password";
1568  values[3] = password;
1569  keywords[4] = "dbname";
1570  values[4] = dbName;
1571  keywords[5] = "fallback_application_name";
1572  values[5] = progname;
1573  keywords[6] = NULL;
1574  values[6] = NULL;
1575 
1576  new_pass = false;
1577 
1578  conn = PQconnectdbParams(keywords, values, true);
1579 
1580  if (!conn)
1581  {
1582  pg_log_error("connection to database \"%s\" failed", dbName);
1583  return NULL;
1584  }
1585 
1586  if (PQstatus(conn) == CONNECTION_BAD &&
1588  !password)
1589  {
1590  PQfinish(conn);
1591  password = simple_prompt("Password: ", false);
1592  new_pass = true;
1593  }
1594  } while (new_pass);
1595 
1596  /* check to see that the backend connection was successfully made */
1597  if (PQstatus(conn) == CONNECTION_BAD)
1598  {
1600  PQfinish(conn);
1601  return NULL;
1602  }
1603 
1604  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:658
int PQconnectionNeedsPassword(const PGconn *conn)
Definition: fe-connect.c:6959
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6855
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4261
@ CONNECTION_BAD
Definition: libpq-fe.h:61
#define PARAMS_ARRAY_SIZE
const char * pghost
Definition: pgbench.c:307
const char * username
Definition: pgbench.c:309
const char * progname
Definition: pgbench.c:312
const char * pgport
Definition: pgbench.c:308
const char * dbName
Definition: pgbench.c:310
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 4472 of file pgbench.c.

4475 {
4476  FILE *logfile = thread->logfile;
4478 
4479  Assert(use_log);
4480 
4481  /*
4482  * Skip the log entry if sampling is enabled and this row doesn't belong
4483  * to the random sample.
4484  */
4485  if (sample_rate != 0.0 &&
4487  return;
4488 
4489  /* should we aggregate the results or not? */
4490  if (agg_interval > 0)
4491  {
4493 
4494  /*
4495  * Loop until we reach the interval of the current moment, and print
4496  * any empty intervals in between (this may happen with very low tps,
4497  * e.g. --rate=0.1).
4498  */
4499 
4500  while ((next = agg->start_time + agg_interval * INT64CONST(1000000)) <= now)
4501  {
4502  double lag_sum = 0.0;
4503  double lag_sum2 = 0.0;
4504  double lag_min = 0.0;
4505  double lag_max = 0.0;
4506  int64 skipped = 0;
4507  int64 serialization_failures = 0;
4508  int64 deadlock_failures = 0;
4509  int64 retried = 0;
4510  int64 retries = 0;
4511 
4512  /* print aggregated report to logfile */
4513  fprintf(logfile, INT64_FORMAT " " INT64_FORMAT " %.0f %.0f %.0f %.0f",
4514  agg->start_time / 1000000, /* seconds since Unix epoch */
4515  agg->cnt,
4516  agg->latency.sum,
4517  agg->latency.sum2,
4518  agg->latency.min,
4519  agg->latency.max);
4520 
4521  if (throttle_delay)
4522  {
4523  lag_sum = agg->lag.sum;
4524  lag_sum2 = agg->lag.sum2;
4525  lag_min = agg->lag.min;
4526  lag_max = agg->lag.max;
4527  }
4528  fprintf(logfile, " %.0f %.0f %.0f %.0f",
4529  lag_sum,
4530  lag_sum2,
4531  lag_min,
4532  lag_max);
4533 
4534  if (latency_limit)
4535  skipped = agg->skipped;
4536  fprintf(logfile, " " INT64_FORMAT, skipped);
4537 
4538  if (max_tries != 1)
4539  {
4540  retried = agg->retried;
4541  retries = agg->retries;
4542  }
4543  fprintf(logfile, " " INT64_FORMAT " " INT64_FORMAT, retried, retries);
4544 
4545  if (failures_detailed)
4546  {
4547  serialization_failures = agg->serialization_failures;
4548  deadlock_failures = agg->deadlock_failures;
4549  }
4551  serialization_failures,
4552  deadlock_failures);
4553 
4554  fputc('\n', logfile);
4555 
4556  /* reset data and move to next interval */
4557  initStats(agg, next);
4558  }
4559 
4560  /* accumulate the current transaction */
4561  accumStats(agg, skipped, latency, lag, st->estatus, st->tries);
4562  }
4563  else
4564  {
4565  /* no, print raw transactions */
4566  if (!skipped && st->estatus == ESTATUS_NO_ERROR)
4567  fprintf(logfile, "%d " INT64_FORMAT " %.0f %d " INT64_FORMAT " "
4568  INT64_FORMAT,
4569  st->id, st->cnt, latency, st->use_file,
4570  now / 1000000, now % 1000000);
4571  else
4572  fprintf(logfile, "%d " INT64_FORMAT " %s %d " INT64_FORMAT " "
4573  INT64_FORMAT,
4574  st->id, st->cnt, getResultString(skipped, st->estatus),
4575  st->use_file, now / 1000000, now % 1000000);
4576 
4577  if (throttle_delay)
4578  fprintf(logfile, " %.0f", lag);
4579  if (max_tries != 1)
4580  fprintf(logfile, " %u", st->tries - 1);
4581  fputc('\n', logfile);
4582  }
static int32 next
Definition: blutils.c:219
static FILE * logfile
Definition: pg_regress.c:102
static void accumStats(StatsData *stats, bool skipped, double lat, double lag, EStatus estatus, int64 tries)
Definition: pgbench.c:1463
uint32 max_tries
Definition: pgbench.c:302
bool use_log
Definition: pgbench.c:269
int agg_interval
Definition: pgbench.c:271
static const char * getResultString(bool skipped, EStatus estatus)
Definition: pgbench.c:4441
static void initStats(StatsData *sd, pg_time_usec_t start)
Definition: pgbench.c:1446
double sample_rate
Definition: pgbench.c:210
bool failures_detailed
Definition: pgbench.c:304
pg_time_usec_t epoch_shift
Definition: pgbench.c:461
pg_time_usec_t start_time
Definition: pgbench.c:390
FILE * logfile
Definition: pgbench.c:672
pg_prng_state ts_sample_rs
Definition: pgbench.c:669

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 3386 of file pgbench.c.

3388 {
3390 
3391  /* We can only retry serialization or deadlock errors. */
3392  if (!canRetryError(st->estatus))
3393  return false;
3394 
3395  /*
3396  * We must have at least one option to limit the retrying of transactions
3397  * that got an error.
3398  */
3400 
3401  /*
3402  * We cannot retry the error if we have reached the maximum number of
3403  * tries.
3404  */
3405  if (max_tries && st->tries >= max_tries)
3406  return false;
3407 
3408  /*
3409  * We cannot retry the error if we spent too much time on this
3410  * transaction.
3411  */
3412  if (latency_limit)
3413  {
3415  if (*now - st->txn_scheduled > latency_limit)
3416  return false;
3417  }
3418 
3419  /*
3420  * We cannot retry the error if the benchmark duration is over.
3421  */
3422  if (timer_exceeded)
3423  return false;
3424 
3425  /* OK */
3426  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 1785 of file pgbench.c.

1787 {
1788  /* total number of variables required now */
1789  needed += variables->nvars;
1790 
1791  if (variables->max_vars < needed)
1792  {
1793  variables->max_vars = needed + VARIABLES_ALLOC_MARGIN;
1794  variables->vars = (Variable *)
1795  pg_realloc(variables->vars, variables->max_vars * sizeof(Variable));
1796  }
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
#define VARIABLES_ALLOC_MARGIN
Definition: pgbench.c:322
Variable * vars
Definition: pgbench.c:346
int nvars
Definition: pgbench.c:347
int max_vars
Definition: pgbench.c:354

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 2830 of file pgbench.c.

2833 {
2834  if (isLazyFunc(func))
2835  return evalLazyFunc(st, func, args, retval);
2836  else
2837  return evalStandardFunc(st, func, args, retval);
static bool isLazyFunc(PgBenchFunction func)
Definition: pgbench.c:2139
static bool evalLazyFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2146
static bool evalStandardFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2263

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 2146 of file pgbench.c.

2149 {
2150  PgBenchValue a1,
2151  a2;
2152  bool ba1,
2153  ba2;
2154 
2155  Assert(isLazyFunc(func) && args != NULL && args->next != NULL);
2156 
2157  /* args points to first condition */
2158  if (!evaluateExpr(st, args->expr, &a1))
2159  return false;
2160 
2161  /* second condition for AND/OR and corresponding branch for CASE */
2162  args = args->next;
2163 
2164  switch (func)
2165  {
2166  case PGBENCH_AND:
2167  if (a1.type == PGBT_NULL)
2168  {
2169  setNullValue(retval);
2170  return true;
2171  }
2172 
2173  if (!coerceToBool(&a1, &ba1))
2174  return false;
2175 
2176  if (!ba1)
2177  {
2178  setBoolValue(retval, false);
2179  return true;
2180  }
2181 
2182  if (!evaluateExpr(st, args->expr, &a2))
2183  return false;
2184 
2185  if (a2.type == PGBT_NULL)
2186  {
2187  setNullValue(retval);
2188  return true;
2189  }
2190  else if (!coerceToBool(&a2, &ba2))
2191  return false;
2192  else
2193  {
2194  setBoolValue(retval, ba2);
2195  return true;
2196  }
2197 
2198  return true;
2199 
2200  case PGBENCH_OR:
2201 
2202  if (a1.type == PGBT_NULL)
2203  {
2204  setNullValue(retval);
2205  return true;
2206  }
2207 
2208  if (!coerceToBool(&a1, &ba1))
2209  return false;
2210 
2211  if (ba1)
2212  {
2213  setBoolValue(retval, true);
2214  return true;
2215  }
2216 
2217  if (!evaluateExpr(st, args->expr, &a2))
2218  return false;
2219 
2220  if (a2.type == PGBT_NULL)
2221  {
2222  setNullValue(retval);
2223  return true;
2224  }
2225  else if (!coerceToBool(&a2, &ba2))
2226  return false;
2227  else
2228  {
2229  setBoolValue(retval, ba2);
2230  return true;
2231  }
2232 
2233  case PGBENCH_CASE:
2234  /* when true, execute branch */
2235  if (valueTruth(&a1))
2236  return evaluateExpr(st, args->expr, retval);
2237 
2238  /* now args contains next condition or final else expression */
2239  args = args->next;
2240 
2241  /* final else case? */
2242  if (args->next == NULL)
2243  return evaluateExpr(st, args->expr, retval);
2244 
2245  /* no, another when, proceed */
2246  return evalLazyFunc(st, PGBENCH_CASE, args, retval);
2247 
2248  default:
2249  /* internal error, cannot get here */
2250  Assert(0);
2251  break;
2252  }
2253  return false;
static const FormData_pg_attribute a1
Definition: heap.c:141
static const FormData_pg_attribute a2
Definition: heap.c:155
static void setNullValue(PgBenchValue *pv)
Definition: pgbench.c:2108
static bool evaluateExpr(CState *st, PgBenchExpr *expr, PgBenchValue *retval)
Definition: pgbench.c:2846
static void setBoolValue(PgBenchValue *pv, bool bval)
Definition: pgbench.c:2116
static bool valueTruth(PgBenchValue *pval)
Definition: pgbench.c:2038
static bool coerceToBool(PgBenchValue *pval, bool *bval)
Definition: pgbench.c:2018
@ 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 2263 of file pgbench.c.

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

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(), generate_unaccent_rules::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 2846 of file pgbench.c.

2848 {
2849  switch (expr->etype)
2850  {
2851  case ENODE_CONSTANT:
2852  {
2853  *retval = expr->u.constant;
2854  return true;
2855  }
2856 
2857  case ENODE_VARIABLE:
2858  {
2859  Variable *var;
2860 
2861  if ((var = lookupVariable(&st->variables, expr->u.variable.varname)) == NULL)
2862  {
2863  pg_log_error("undefined variable \"%s\"", expr->u.variable.varname);
2864  return false;
2865  }
2866 
2867  if (!makeVariableValue(var))
2868  return false;
2869 
2870  *retval = var->value;
2871  return true;
2872  }
2873 
2874  case ENODE_FUNCTION:
2875  return evalFunc(st,
2876  expr->u.function.function,
2877  expr->u.function.args,
2878  retval);
2879 
2880  default:
2881  /* internal error which should never occur */
2882  pg_fatal("unexpected enode type in evaluation: %d", expr->etype);
2883  }
static Variable * lookupVariable(Variables *variables, char *name)
Definition: pgbench.c:1616
static bool evalFunc(CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2830
static bool makeVariableValue(Variable *var)
Definition: pgbench.c:1676
@ ENODE_VARIABLE
Definition: pgbench.h:60
@ ENODE_CONSTANT
Definition: pgbench.h:59
@ ENODE_FUNCTION
Definition: pgbench.h:61
Variables variables
Definition: pgbench.c:625
PgBenchValue constant
Definition: pgbench.h:115
PgBenchFunction function
Definition: pgbench.h:122
union PgBenchExpr::@35 u
struct PgBenchExpr::@35::@36 variable
PgBenchExprType etype
Definition: pgbench.h:112
PgBenchValue value
Definition: pgbench.c:338

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 3341 of file pgbench.c.

3343 {
3344  char *var;
3345  int usec;
3346 
3347  if (*argv[1] == ':')
3348  {
3349  if ((var = getVariable(variables, argv[1] + 1)) == NULL)
3350  {
3351  pg_log_error("%s: undefined variable \"%s\"", argv[0], argv[1] + 1);
3352  return false;
3353  }
3354 
3355  usec = atoi(var);
3356 
3357  /* Raise an error if the value of a variable is not a number */
3358  if (usec == 0 && !isdigit((unsigned char) *var))
3359  {
3360  pg_log_error("%s: invalid sleep time \"%s\" for variable \"%s\"",
3361  argv[0], var, argv[1] + 1);
3362  return false;
3363  }
3364  }
3365  else
3366  usec = atoi(argv[1]);
3367 
3368  if (argc > 2)
3369  {
3370  if (pg_strcasecmp(argv[2], "ms") == 0)
3371  usec *= 1000;
3372  else if (pg_strcasecmp(argv[2], "s") == 0)
3373  usec *= 1000000;
3374  }
3375  else
3376  usec *= 1000000;
3377 
3378  *usecs = usec;
3379  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 4236 of file pgbench.c.

4238 {
4239  Command *command = sql_script[st->use_file].commands[st->command];
4240  int argc;
4241  char **argv;
4242 
4243  Assert(command != NULL && command->type == META_COMMAND);
4244 
4245  argc = command->argc;
4246  argv = command->argv;
4247 
4249  {
4251 
4252  initPQExpBuffer(&buf);
4253 
4254  printfPQExpBuffer(&buf, "client %d executing \\%s", st->id, argv[0]);
4255  for (int i = 1; i < argc; i++)
4256  appendPQExpBuffer(&buf, " %s", argv[i]);
4257 
4258  pg_log_debug("%s", buf.data);
4259 
4260  termPQExpBuffer(&buf);
4261  }
4262 
4263  if (command->meta == META_SLEEP)
4264  {
4265  int usec;
4266 
4267  /*
4268  * A \sleep doesn't execute anything, we just get the delay from the
4269  * argument, and enter the CSTATE_SLEEP state. (The per-command
4270  * latency will be recorded in CSTATE_SLEEP state, not here, after the
4271  * delay has elapsed.)
4272  */
4273  if (!evaluateSleep(&st->variables, argc, argv, &usec))
4274  {
4275  commandFailed(st, "sleep", "execution of meta-command failed");
4276  return CSTATE_ABORTED;
4277  }
4278 
4280  st->sleep_until = (*now) + usec;
4281  return CSTATE_SLEEP;
4282  }
4283  else if (command->meta == META_SET)
4284  {
4285  PgBenchExpr *expr = command->expr;
4286  PgBenchValue result;
4287 
4288  if (!evaluateExpr(st, expr, &result))
4289  {
4290  commandFailed(st, argv[0], "evaluation of meta-command failed");
4291  return CSTATE_ABORTED;
4292  }
4293 
4294  if (!putVariableValue(&st->variables, argv[0], argv[1], &result))
4295  {
4296  commandFailed(st, "set", "assignment of meta-command failed");
4297  return CSTATE_ABORTED;
4298  }
4299  }
4300  else if (command->meta == META_IF)
4301  {
4302  /* backslash commands with an expression to evaluate */
4303  PgBenchExpr *expr = command->expr;
4304  PgBenchValue result;
4305  bool cond;
4306 
4307  if (!evaluateExpr(st, expr, &result))
4308  {
4309  commandFailed(st, argv[0], "evaluation of meta-command failed");
4310  return CSTATE_ABORTED;
4311  }
4312 
4313  cond = valueTruth(&result);
4315  }
4316  else if (command->meta == META_ELIF)
4317  {
4318  /* backslash commands with an expression to evaluate */
4319  PgBenchExpr *expr = command->expr;
4320  PgBenchValue result;
4321  bool cond;
4322 
4324  {
4325  /* elif after executed block, skip eval and wait for endif. */
4327  return CSTATE_END_COMMAND;
4328  }
4329 
4330  if (!evaluateExpr(st, expr, &result))
4331  {
4332  commandFailed(st, argv[0], "evaluation of meta-command failed");
4333  return CSTATE_ABORTED;
4334  }
4335 
4336  cond = valueTruth(&result);
4339  }
4340  else if (command->meta == META_ELSE)
4341  {
4342  switch (conditional_stack_peek(st->cstack))
4343  {
4344  case IFSTATE_TRUE:
4346  break;
4347  case IFSTATE_FALSE: /* inconsistent if active */
4348  case IFSTATE_IGNORED: /* inconsistent if active */
4349  case IFSTATE_NONE: /* else without if */
4350  case IFSTATE_ELSE_TRUE: /* else after else */
4351  case IFSTATE_ELSE_FALSE: /* else after else */
4352  default:
4353  /* dead code if conditional check is ok */
4354  Assert(false);
4355  }
4356  }
4357  else if (command->meta == META_ENDIF)
4358  {
4361  }
4362  else if (command->meta == META_SETSHELL)
4363  {
4364  if (!runShellCommand(&st->variables, argv[1], argv + 2, argc - 2))
4365  {
4366  commandFailed(st, "setshell", "execution of meta-command failed");
4367  return CSTATE_ABORTED;
4368  }
4369  }
4370  else if (command->meta == META_SHELL)
4371  {
4372  if (!runShellCommand(&st->variables, NULL, argv + 1, argc - 1))
4373  {
4374  commandFailed(st, "shell", "execution of meta-command failed");
4375  return CSTATE_ABORTED;
4376  }
4377  }
4378  else if (command->meta == META_STARTPIPELINE)
4379  {
4380  /*
4381  * In pipeline mode, we use a workflow based on libpq pipeline
4382  * functions.
4383  */
4384  if (querymode == QUERY_SIMPLE)
4385  {
4386  commandFailed(st, "startpipeline", "cannot use pipeline mode with the simple query protocol");
4387  return CSTATE_ABORTED;
4388  }
4389 
4390  if (PQpipelineStatus(st->con) != PQ_PIPELINE_OFF)
4391  {
4392  commandFailed(st, "startpipeline", "already in pipeline mode");
4393  return CSTATE_ABORTED;
4394  }
4395  if (PQenterPipelineMode(st->con) == 0)
4396  {
4397  commandFailed(st, "startpipeline", "failed to enter pipeline mode");
4398  return CSTATE_ABORTED;
4399  }
4400  }
4401  else if (command->meta == META_ENDPIPELINE)
4402  {
4403  if (PQpipelineStatus(st->con) != PQ_PIPELINE_ON)
4404  {
4405  commandFailed(st, "endpipeline", "not in pipeline mode");
4406  return CSTATE_ABORTED;
4407  }
4408  if (!PQpipelineSync(st->con))
4409  {
4410  commandFailed(st, "endpipeline", "failed to send a pipeline sync");
4411  return CSTATE_ABORTED;
4412  }
4413  /* Now wait for the PGRES_PIPELINE_SYNC and exit pipeline mode there */
4414  /* collect pending results before getting out of pipeline mode */
4415  return CSTATE_WAIT_RESULT;
4416  }
4417 
4418  /*
4419  * executing the expression or shell command might have taken a
4420  * non-negligible amount of time, so reset 'now'
4421  */
4422  *now = 0;
4423 
4424  return CSTATE_END_COMMAND;
int PQenterPipelineMode(PGconn *conn)
Definition: fe-exec.c:2980
enum pg_log_level __pg_log_level
Definition: logging.c:21
@ PG_LOG_DEBUG
Definition: logging.h:26
static QueryMode querymode
Definition: pgbench.c:722
static bool runShellCommand(Variables *variables, char *variable, char **argv, int argc)
Definition: pgbench.c:2929
static bool evaluateSleep(Variables *variables, int argc, char **argv, int *usecs)
Definition: pgbench.c:3341
static bool putVariableValue(Variables *variables, const char *context, char *name, const PgBenchValue *value)
Definition: pgbench.c:1865
pg_time_usec_t sleep_until
Definition: pgbench.c:629

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, now(), PG_LOG_DEBUG, pg_log_debug, pg_time_now_lazy(), PQ_PIPELINE_OFF, PQ_PIPELINE_ON, PQenterPipelineMode(), PQpipelineStatus(), PQpipelineSync(), printfPQExpBuffer(), putVariableValue(), 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 1512 of file pgbench.c.

1514 {
1515  PGresult *res;
1516 
1517  res = PQexec(con, sql);
1519  {
1520  pg_log_error("query failed: %s", PQerrorMessage(con));
1521  pg_log_error_detail("Query was: %s", sql);
1522  exit(1);
1523  }
1524  PQclear(res);
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2273

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 6014 of file pgbench.c.

6016 {
6017  int i,
6018  found = 0,
6019  len = strlen(name);
6020  const BuiltinScript *result = NULL;
6021 
6022  for (i = 0; i < lengthof(builtin_script); i++)
6023  {
6024  if (strncmp(builtin_script[i].name, name, len) == 0)
6025  {
6026  result = &builtin_script[i];
6027  found++;
6028  }
6029  }
6030 
6031  /* ok, unambiguous result */
6032  if (found == 1)
6033  return result;
6034 
6035  /* error cases */
6036  if (found == 0)
6037  pg_log_error("no builtin script found for name \"%s\"", name);
6038  else /* found > 1 */
6039  pg_log_error("ambiguous builtin name: %d builtin scripts found for prefix \"%s\"", found, name);
6040 
6042  exit(1);
#define lengthof(array)
Definition: c.h:734
const void size_t len
static void listAvailableScripts(void)
Definition: pgbench.c:6002
static const BuiltinScript builtin_script[]
Definition: pgbench.c:785

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 7568 of file pgbench.c.

7570 {
7571  if (st->con != NULL)
7572  {
7573  PQfinish(st->con);
7574  st->con = NULL;
7575  }

References CState::con, and PQfinish().

Referenced by advanceConnectionState(), and disconnect_all().

◆ free_command()

static void free_command ( Command command)
static

Definition at line 5474 of file pgbench.c.

5476 {
5477  termPQExpBuffer(&command->lines);
5478  if (command->first_line)
5479  pg_free(command->first_line);
5480  for (int i = 0; i < command->argc; i++)
5481  pg_free(command->argv[i]);
5482  if (command->varprefix)
5483  pg_free(command->varprefix);
5484 
5485  /*
5486  * It should also free expr recursively, but this is currently not needed
5487  * as only gset commands (which do not have an expression) are freed.
5488  */
5489  pg_free(command);
void pg_free(void *ptr)
Definition: fe_memutils.c:105

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 7739 of file pgbench.c.

7741 {
7742  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 1107 of file pgbench.c.

1110 {
1111  double cut,
1112  uniform,
1113  rand;
1114 
1115  /* abort if wrong parameter, but must really be checked beforehand */
1116  Assert(parameter > 0.0);
1117  cut = exp(-parameter);
1118  /* pg_prng_double value in [0, 1), uniform in (0, 1] */
1119  uniform = 1.0 - pg_prng_double(state);
1120 
1121  /*
1122  * inner expression in (cut, 1] (if parameter > 0), rand in [0, 1)
1123  */
1124  Assert((1.0 - cut) != 0.0);
1125  rand = -log(cut + (1.0 - cut) * uniform) / parameter;
1126  /* return int64 random number within between min and max */
1127  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 4430 of file pgbench.c.

4432 {
4433  return (stats->serialization_failures +
4434  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 1131 of file pgbench.c.

1134 {
1135  double stdev;
1136  double rand;
1137 
1138  /* abort if parameter is too low, but must really be checked beforehand */
1139  Assert(parameter >= MIN_GAUSSIAN_PARAM);
1140 
1141  /*
1142  * Get user specified random number from this loop, with -parameter <
1143  * stdev <= parameter
1144  *
1145  * This loop is executed until the number is in the expected range.
1146  *
1147  * As the minimum parameter is 2.0, the probability of looping is low:
1148  * sqrt(-2 ln(r)) <= 2 => r >= e^{-2} ~ 0.135, then when taking the
1149  * average sinus multiplier as 2/pi, we have a 8.6% looping probability in
1150  * the worst case. For a parameter value of 5.0, the looping probability
1151  * is about e^{-5} * 2 / pi ~ 0.43%.
1152  */
1153  do
1154  {
1155  /*
1156  * pg_prng_double generates [0, 1), but for the basic version of the
1157  * Box-Muller transform the two uniformly distributed random numbers
1158  * are expected to be in (0, 1] (see
1159  * https://en.wikipedia.org/wiki/Box-Muller_transform)
1160  */
1161  double rand1 = 1.0 - pg_prng_double(state);
1162  double rand2 = 1.0 - pg_prng_double(state);
1163 
1164  /* Box-Muller basic form transform */
1165  double var_sqrt = sqrt(-2.0 * log(rand1));
1166 
1167  stdev = var_sqrt * sin(2.0 * M_PI * rand2);
1168 
1169  /*
1170  * we may try with cos, but there may be a bias induced if the
1171  * previous value fails the test. To be on the safe side, let us try
1172  * over.
1173  */
1174  }
1175  while (stdev < -parameter || stdev >= parameter);
1176 
1177  /* stdev is in [-parameter, parameter), normalization to [0,1) */
1178  rand = (stdev + parameter) / (parameter * 2.0);
1179 
1180  /* return int64 random number within between min and max */
1181  return min + (int64) ((max - min + 1) * rand);

References Assert(), M_PI, MIN_GAUSSIAN_PARAM, and pg_prng_double().

Referenced by evalStandardFunc().

◆ getHashFnv1a()

static int64 getHashFnv1a ( int64  val,
uint64  seed 
)
static

Definition at line 1257 of file pgbench.c.

1259 {
1260  int64 result;
1261  int i;
1262 
1263  result = FNV_OFFSET_BASIS ^ seed;
1264  for (i = 0; i < 8; ++i)
1265  {
1266  int32 octet = val & 0xff;
1267 
1268  val = val >> 8;
1269  result = result ^ octet;
1270  result = result * FNV_PRIME;
1271  }
1272 
1273  return result;
signed int int32
Definition: c.h:429
#define FNV_OFFSET_BASIS
Definition: pgbench.c:87
#define FNV_PRIME
Definition: pgbench.c:86

References FNV_OFFSET_BASIS, FNV_PRIME, i, and val.

Referenced by evalStandardFunc().

◆ getHashMurmur2()

static int64 getHashMurmur2 ( int64  val,
uint64  seed 
)
static

Definition at line 1282 of file pgbench.c.

1284 {
1285  uint64 result = seed ^ MM2_MUL_TIMES_8; /* sizeof(int64) */
1286  uint64 k = (uint64) val;
1287 
1288  k *= MM2_MUL;
1289  k ^= k >> MM2_ROT;
1290  k *= MM2_MUL;
1291 
1292  result ^= k;
1293  result *= MM2_MUL;
1294 
1295  result ^= result >> MM2_ROT;
1296  result *= MM2_MUL;
1297  result ^= result >> MM2_ROT;
1298 
1299  return (int64) result;
#define MM2_MUL_TIMES_8
Definition: pgbench.c:89
#define MM2_ROT
Definition: pgbench.c:90
#define MM2_MUL
Definition: pgbench.c:88

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 2889 of file pgbench.c.

2891 {
2892  MetaCommand mc;
2893 
2894  if (cmd == NULL)
2895  mc = META_NONE;
2896  else if (pg_strcasecmp(cmd, "set") == 0)
2897  mc = META_SET;
2898  else if (pg_strcasecmp(cmd, "setshell") == 0)
2899  mc = META_SETSHELL;
2900  else if (pg_strcasecmp(cmd, "shell") == 0)
2901  mc = META_SHELL;
2902  else if (pg_strcasecmp(cmd, "sleep") == 0)
2903  mc = META_SLEEP;
2904  else if (pg_strcasecmp(cmd, "if") == 0)
2905  mc = META_IF;
2906  else if (pg_strcasecmp(cmd, "elif") == 0)
2907  mc = META_ELIF;
2908  else if (pg_strcasecmp(cmd, "else") == 0)
2909  mc = META_ELSE;
2910  else if (pg_strcasecmp(cmd, "endif") == 0)
2911  mc = META_ENDIF;
2912  else if (pg_strcasecmp(cmd, "gset") == 0)
2913  mc = META_GSET;
2914  else if (pg_strcasecmp(cmd, "aset") == 0)
2915  mc = META_ASET;
2916  else if (pg_strcasecmp(cmd, "startpipeline") == 0)
2917  mc = META_STARTPIPELINE;
2918  else if (pg_strcasecmp(cmd, "endpipeline") == 0)
2919  mc = META_ENDPIPELINE;
2920  else
2921  mc = META_NONE;
2922  return mc;
MetaCommand
Definition: pgbench.c:698

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, and pg_strcasecmp().

Referenced by process_backslash_command().

◆ getPoissonRand()

static int64 getPoissonRand ( pg_prng_state state,
double  center 
)
static

Definition at line 1191 of file pgbench.c.

1193 {
1194  /*
1195  * Use inverse transform sampling to generate a value > 0, such that the
1196  * expected (i.e. average) value is the given argument.
1197  */
1198  double uniform;
1199 
1200  /* pg_prng_double value in [0, 1), uniform in (0, 1] */
1201  uniform = 1.0 - pg_prng_double(state);
1202 
1203  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 1986 of file pgbench.c.

1989 {
1990  int i;
1991 
1992  for (i = 0; i < command->argc - 1; i++)
1993  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 1096 of file pgbench.c.

1098 {
1099  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:138

References pg_prng_uint64_range().

Referenced by chooseScript(), and evalStandardFunc().

◆ getResultString()

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

Definition at line 4441 of file pgbench.c.

4443 {
4444  if (skipped)
4445  return "skipped";
4446  else if (failures_detailed)
4447  {
4448  switch (estatus)
4449  {
4451  return "serialization";
4453  return "deadlock";
4454  default:
4455  /* internal error which should never occur */
4456  pg_fatal("unexpected error status: %d", estatus);
4457  }
4458  }
4459  else
4460  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 3168 of file pgbench.c.

3170 {
3171  if (sqlState != NULL)
3172  {
3173  if (strcmp(sqlState, ERRCODE_T_R_SERIALIZATION_FAILURE) == 0)
3175  else if (strcmp(sqlState, ERRCODE_T_R_DEADLOCK_DETECTED) == 0)
3176  return ESTATUS_DEADLOCK_ERROR;
3177  }
3178 
3179  return ESTATUS_OTHER_SQL_ERROR;
#define ERRCODE_T_R_DEADLOCK_DETECTED
Definition: pgbench.c:80
#define ERRCODE_T_R_SERIALIZATION_FAILURE
Definition: pgbench.c:79

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 5205 of file pgbench.c.

5207 {
5208  PGresult *res;
5209 
5210  /*
5211  * get the scaling factor that should be same as count(*) from
5212  * pgbench_branches if this is not a custom query
5213  */
5214  res = PQexec(con, "select count(*) from pgbench_branches");
5216  {
5217  char *sqlState = PQresultErrorField(res, PG_DIAG_SQLSTATE);
5218 
5219  pg_log_error("could not count number of branches: %s", PQerrorMessage(con));
5220 
5221  if (sqlState && strcmp(sqlState, ERRCODE_UNDEFINED_TABLE) == 0)
5222  pg_log_error_hint("Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".",
5223  PQdb(con));
5224 
5225  exit(1);
5226  }
5227  scale = atoi(PQgetvalue(res, 0, 0));
5228  if (scale < 0)
5229  pg_fatal("invalid count(*) from pgbench_branches: \"%s\"",
5230  PQgetvalue(res, 0, 0));
5231  PQclear(res);
5232 
5233  /* warn if we override user-given -s switch */
5234  if (scale_given)
5235  pg_log_warning("scale option ignored, using count from pgbench_branches table (%d)",
5236  scale);
5237 
5238  /*
5239  * Get the partition information for the first "pgbench_accounts" table
5240  * found in search_path.
5241  *
5242  * The result is empty if no "pgbench_accounts" is found.
5243  *
5244  * Otherwise, it always returns one row even if the table is not
5245  * partitioned (in which case the partition strategy is NULL).
5246  *
5247  * The number of partitions can be 0 even for partitioned tables, if no
5248  * partition is attached.
5249  *
5250  * We assume no partitioning on any failure, so as to avoid failing on an
5251  * old version without "pg_partitioned_table".
5252  */
5253  res = PQexec(con,
5254  "select o.n, p.partstrat, pg_catalog.count(i.inhparent) "
5255  "from pg_catalog.pg_class as c "
5256  "join pg_catalog.pg_namespace as n on (n.oid = c.relnamespace) "
5257  "cross join lateral (select pg_catalog.array_position(pg_catalog.current_schemas(true), n.nspname)) as o(n) "
5258  "left join pg_catalog.pg_partitioned_table as p on (p.partrelid = c.oid) "
5259  "left join pg_catalog.pg_inherits as i on (c.oid = i.inhparent) "
5260  "where c.relname = 'pgbench_accounts' and o.n is not null "
5261  "group by 1, 2 "
5262  "order by 1 asc "
5263  "limit 1");
5264 
5266  {
5267  /* probably an older version, coldly assume no partitioning */
5269  partitions = 0;
5270  }
5271  else if (PQntuples(res) == 0)
5272  {
5273  /*
5274  * This case is unlikely as pgbench already found "pgbench_branches"
5275  * above to compute the scale.
5276  */
5277  pg_log_error("no pgbench_accounts table found in search_path");
5278  pg_log_error_hint("Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\".", PQdb(con));
5279  exit(1);
5280  }
5281  else /* PQntupes(res) == 1 */
5282  {
5283  /* normal case, extract partition information */
5284  if (PQgetisnull(res, 0, 1))
5286  else
5287  {
5288  char *ps = PQgetvalue(res, 0, 1);
5289 
5290  /* column must be there */
5291  Assert(ps != NULL);
5292 
5293  if (strcmp(ps, "r") == 0)
5295  else if (strcmp(ps, "h") == 0)
5297  else
5298  {
5299  /* possibly a newer version with new partition method */
5300  pg_fatal("unexpected partition method: \"%s\"", ps);
5301  }
5302  }
5303 
5304  partitions = atoi(PQgetvalue(res, 0, 2));
5305  }
5306 
5307  PQclear(res);
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:6754
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3340
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3735
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3760
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3325
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:100
#define pg_log_error_hint(...)
Definition: logging.h:112
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:81
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57

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(), res, and scale.

Referenced by main().

◆ getTransactionStatus()

static TStatus getTransactionStatus ( PGconn con)
static

Definition at line 3472 of file pgbench.c.

3474 {
3475  PGTransactionStatusType tx_status;
3476 
3477  tx_status = PQtransactionStatus(con);
3478  switch (tx_status)
3479  {
3480  case PQTRANS_IDLE:
3481  return TSTATUS_IDLE;
3482  case PQTRANS_INTRANS:
3483  case PQTRANS_INERROR:
3484  return TSTATUS_IN_BLOCK;
3485  case PQTRANS_UNKNOWN:
3486  /* PQTRANS_UNKNOWN is expected given a broken connection */
3487  if (PQstatus(con) == CONNECTION_BAD)
3488  return TSTATUS_CONN_ERROR;
3489  /* fall through */
3490  case PQTRANS_ACTIVE:
3491  default:
3492 
3493  /*
3494  * We cannot find out whether we are in a transaction block or
3495  * not. Internal error which should never occur.
3496  */
3497  pg_log_error("unexpected transaction status %d", tx_status);
3498  return TSTATUS_OTHER_ERROR;
3499  }
3500 
3501  /* not reached */
3502  Assert(false);
3503  return TSTATUS_OTHER_ERROR;
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:6863
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 1643 of file pgbench.c.

1645 {
1646  Variable *var;
1647  char stringform[64];
1648 
1649  var = lookupVariable(variables, name);
1650  if (var == NULL)
1651  return NULL; /* not found */
1652 
1653  if (var->svalue)
1654  return var->svalue; /* we have it in string form */
1655 
1656  /* We need to produce a string equivalent of the value */
1657  Assert(var->value.type != PGBT_NO_VALUE);
1658  if (var->value.type == PGBT_NULL)
1659  snprintf(stringform, sizeof(stringform), "NULL");
1660  else if (var->value.type == PGBT_BOOLEAN)
1661  snprintf(stringform, sizeof(stringform),
1662  "%s", var->value.u.bval ? "true" : "false");
1663  else if (var->value.type == PGBT_INT)
1664  snprintf(stringform, sizeof(stringform),
1665  INT64_FORMAT, var->value.u.ival);
1666  else if (var->value.type == PGBT_DOUBLE)
1667  snprintf(stringform, sizeof(stringform),
1668  "%.*g", DBL_DIG, var->value.u.dval);
1669  else /* internal error, unexpected type */
1670  Assert(0);
1671  var->svalue = pg_strdup(stringform);
1672  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:225
char * svalue
Definition: pgbench.c:337

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 1243 of file pgbench.c.

1245 {
1246  int64 n = max - min + 1;
1247 
1248  /* abort if parameter is invalid */
1250 
1251  return min - 1 + computeIterativeZipfian(state, n, s);
static int64 computeIterativeZipfian(pg_prng_state *state, int64 n, double s)
Definition: pgbench.c:1213

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 7584 of file pgbench.c.

7586 {
7587  timer_exceeded = true;

References timer_exceeded.

Referenced by setalarm().

◆ initCreateFKeys()

static void initCreateFKeys ( PGconn con)
static

Definition at line 5074 of file pgbench.c.

5076 {
5077  static const char *const DDLKEYs[] = {
5078  "alter table pgbench_tellers add constraint pgbench_tellers_bid_fkey foreign key (bid) references pgbench_branches",
5079  "alter table pgbench_accounts add constraint pgbench_accounts_bid_fkey foreign key (bid) references pgbench_branches",
5080  "alter table pgbench_history add constraint pgbench_history_bid_fkey foreign key (bid) references pgbench_branches",
5081  "alter table pgbench_history add constraint pgbench_history_tid_fkey foreign key (tid) references pgbench_tellers",
5082  "alter table pgbench_history add constraint pgbench_history_aid_fkey foreign key (aid) references pgbench_accounts"
5083  };
5084  int i;
5085 
5086  fprintf(stderr, "creating foreign keys...\n");
5087  for (i = 0; i < lengthof(DDLKEYs); i++)
5088  {
5089  executeStatement(con, DDLKEYs[i]);
5090  }

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

Referenced by runInitSteps().

◆ initCreatePKeys()

static void initCreatePKeys ( PGconn con)
static

Definition at line 5036 of file pgbench.c.

5038 {
5039  static const char *const DDLINDEXes[] = {
5040  "alter table pgbench_branches add primary key (bid)",
5041  "alter table pgbench_tellers add primary key (tid)",
5042  "alter table pgbench_accounts add primary key (aid)"
5043  };
5044  int i;
5045  PQExpBufferData query;
5046 
5047  fprintf(stderr, "creating primary keys...\n");
5048  initPQExpBuffer(&query);
5049 
5050  for (i = 0; i < lengthof(DDLINDEXes); i++)
5051  {
5052  resetPQExpBuffer(&query);
5053  appendPQExpBufferStr(&query, DDLINDEXes[i]);
5054 
5055  if (index_tablespace != NULL)
5056  {
5057  char *escape_tablespace;
5058 
5059  escape_tablespace = PQescapeIdentifier(con, index_tablespace,
5060  strlen(index_tablespace));
5061  appendPQExpBuffer(&query, " using index tablespace %s", escape_tablespace);
5062  PQfreemem(escape_tablespace);
5063  }
5064 
5065  executeStatement(con, query.data);
5066  }
5067 
5068  termPQExpBuffer(&query);
void PQfreemem(void *ptr)
Definition: fe-exec.c:3891
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
Definition: fe-exec.c:4172
char * index_tablespace
Definition: pgbench.c:230
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148

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 4734 of file pgbench.c.

4736 {
4737  /*
4738  * Note: TPC-B requires at least 100 bytes per row, and the "filler"
4739  * fields in these table declarations were intended to comply with that.
4740  * The pgbench_accounts table complies with that because the "filler"
4741  * column is set to blank-padded empty string. But for all other tables
4742  * the columns default to NULL and so don't actually take any space. We
4743  * could fix that by giving them non-null default values. However, that
4744  * would completely break comparability of pgbench results with prior
4745  * versions. Since pgbench has never pretended to be fully TPC-B compliant
4746  * anyway, we stick with the historical behavior.
4747  */
4748  struct ddlinfo
4749  {
4750  const char *table; /* table name */
4751  const char *smcols; /* column decls if accountIDs are 32 bits */
4752  const char *bigcols; /* column decls if accountIDs are 64 bits */
4753  int declare_fillfactor;
4754  };
4755  static const struct ddlinfo DDLs[] = {
4756  {
4757  "pgbench_history",
4758  "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
4759  "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)",
4760  0
4761  },
4762  {
4763  "pgbench_tellers",
4764  "tid int not null,bid int,tbalance int,filler char(84)",
4765  "tid int not null,bid int,tbalance int,filler char(84)",
4766  1
4767  },
4768  {
4769  "pgbench_accounts",
4770  "aid int not null,bid int,abalance int,filler char(84)",
4771  "aid bigint not null,bid int,abalance int,filler char(84)",
4772  1
4773  },
4774  {
4775  "pgbench_branches",
4776  "bid int not null,bbalance int,filler char(88)",
4777  "bid int not null,bbalance int,filler char(88)",
4778  1
4779  }
4780  };
4781  int i;
4782  PQExpBufferData query;
4783 
4784  fprintf(stderr, "creating tables...\n");
4785 
4786  initPQExpBuffer(&query);
4787 
4788  for (i = 0; i < lengthof(DDLs); i++)
4789  {
4790  const struct ddlinfo *ddl = &DDLs[i];
4791 
4792  /* Construct new create table statement. */
4793  printfPQExpBuffer(&query, "create%s table %s(%s)",
4794  unlogged_tables ? " unlogged" : "",
4795  ddl->table,
4796  (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols);
4797 
4798  /* Partition pgbench_accounts table */
4799  if (partition_method != PART_NONE && strcmp(ddl->table, "pgbench_accounts") == 0)
4800  appendPQExpBuffer(&query,
4801  " partition by %s (aid)", PARTITION_METHOD[partition_method]);
4802  else if (ddl->declare_fillfactor)
4803  {
4804  /* fillfactor is only expected on actual tables */
4805  appendPQExpBuffer(&query, " with (fillfactor=%d)", fillfactor);
4806  }
4807 
4808  if (tablespace != NULL)
4809  {
4810  char *escape_tablespace;
4811 
4812  escape_tablespace = PQescapeIdentifier(con, tablespace, strlen(tablespace));
4813  appendPQExpBuffer(&query, " tablespace %s", escape_tablespace);
4814  PQfreemem(escape_tablespace);
4815  }
4816 
4817  executeStatement(con, query.data);
4818  }
4819 
4820  termPQExpBuffer(&query);
4821 
4822  if (partition_method != PART_NONE)
4823  createPartitions(con);
static void createPartitions(PGconn *con)
Definition: pgbench.c:4665
static const char * PARTITION_METHOD[]
Definition: pgbench.c:247
#define SCALE_32BIT_THRESHOLD
Definition: pgbench.c:267
char * tablespace
Definition: pgbench.c:229

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 4643 of file pgbench.c.

4645 {
4646  fprintf(stderr, "dropping old tables...\n");
4647 
4648  /*
4649  * We drop all the tables in one command, so that whether there are
4650  * foreign key dependencies or not doesn't matter.
4651  */
4652  executeStatement(con, "drop table if exists "
4653  "pgbench_accounts, "
4654  "pgbench_branches, "
4655  "pgbench_history, "
4656  "pgbench_tellers");

References executeStatement(), and fprintf.

Referenced by runInitSteps().

◆ initGenerateDataClientSide()

static void initGenerateDataClientSide ( PGconn con)
static

Definition at line 4842 of file pgbench.c.

4844 {
4845  PQExpBufferData sql;
4846  PGresult *res;
4847  int i;
4848  int64 k;
4849  char *copy_statement;
4850 
4851  /* used to track elapsed time and estimate of the remaining time */
4852  pg_time_usec_t start;
4853  int log_interval = 1;
4854 
4855  /* Stay on the same line if reporting to a terminal */
4856  char eol = isatty(fileno(stderr)) ? '\r' : '\n';
4857 
4858  fprintf(stderr, "generating data (client-side)...\n");
4859 
4860  /*
4861  * we do all of this in one transaction to enable the backend's
4862  * data-loading optimizations
4863  */
4864  executeStatement(con, "begin");
4865 
4866  /* truncate away any old data */
4867  initTruncateTables(con);
4868 
4869  initPQExpBuffer(&sql);
4870 
4871  /*
4872  * fill branches, tellers, accounts in that order in case foreign keys
4873  * already exist
4874  */
4875  for (i = 0; i < nbranches * scale; i++)
4876  {
4877  /* "filler" column defaults to NULL */
4878  printfPQExpBuffer(&sql,
4879  "insert into pgbench_branches(bid,bbalance) values(%d,0)",
4880  i + 1);
4881  executeStatement(con, sql.data);
4882  }
4883 
4884  for (i = 0; i < ntellers * scale; i++)
4885  {
4886  /* "filler" column defaults to NULL */
4887  printfPQExpBuffer(&sql,
4888  "insert into pgbench_tellers(tid,bid,tbalance) values (%d,%d,0)",
4889  i + 1, i / ntellers + 1);
4890  executeStatement(con, sql.data);
4891  }
4892 
4893  /*
4894  * accounts is big enough to be worth using COPY and tracking runtime
4895  */
4896 
4897  /* use COPY with FREEZE on v14 and later without partitioning */
4898  if (partitions == 0 && PQserverVersion(con) >= 140000)
4899  copy_statement = "copy pgbench_accounts from stdin with (freeze on)";
4900  else
4901  copy_statement = "copy pgbench_accounts from stdin";
4902 
4903  res = PQexec(con, copy_statement);
4904 
4906  pg_fatal("unexpected copy in result: %s", PQerrorMessage(con));
4907  PQclear(res);
4908 
4909  start = pg_time_now();
4910 
4911  for (k = 0; k < (int64) naccounts * scale; k++)
4912  {
4913  int64 j = k + 1;
4914 
4915  /* "filler" column defaults to blank padded empty string */
4916  printfPQExpBuffer(&sql,
4917  INT64_FORMAT "\t" INT64_FORMAT "\t%d\t\n",
4918  j, k / naccounts + 1, 0);
4919  if (PQputline(con, sql.data))
4920  pg_fatal("PQputline failed");
4921 
4922  if (CancelRequested)
4923  break;
4924 
4925  /*
4926  * If we want to stick with the original logging, print a message each
4927  * 100k inserted rows.
4928  */
4929  if ((!use_quiet) && (j % 100000 == 0))
4930  {
4931  double elapsed_sec = PG_TIME_GET_DOUBLE(pg_time_now() - start);
4932  double remaining_sec = ((double) scale * naccounts - j) * elapsed_sec / j;
4933 
4934  fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s)%c",
4935  j, (int64) naccounts * scale,
4936  (int) (((int64) j * 100) / (naccounts * (int64) scale)),
4937  elapsed_sec, remaining_sec, eol);
4938  }
4939  /* let's not call the timing for each row, but only each 100 rows */
4940  else if (use_quiet && (j % 100 == 0))
4941  {
4942  double elapsed_sec = PG_TIME_GET_DOUBLE(pg_time_now() - start);
4943  double remaining_sec = ((double) scale * naccounts - j) * elapsed_sec / j;
4944 
4945  /* have we reached the next interval (or end)? */
4946  if ((j == scale * naccounts) || (elapsed_sec >= log_interval * LOG_STEP_SECONDS))
4947  {
4948  fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s)%c",
4949  j, (int64) naccounts * scale,
4950  (int) (((int64) j * 100) / (naccounts * (int64) scale)), elapsed_sec, remaining_sec, eol);
4951 
4952  /* skip to the next interval */
4953  log_interval = (int) ceil(elapsed_sec / LOG_STEP_SECONDS);
4954  }
4955  }
4956  }
4957 
4958  if (eol != '\n')
4959  fputc('\n', stderr); /* Need to move to next line */
4960 
4961  if (PQputline(con, "\\.\n"))
4962  pg_fatal("very last PQputline failed");
4963  if (PQendcopy(con))
4964  pg_fatal("PQendcopy failed");
4965 
4966  termPQExpBuffer(&sql);
4967 
4968  executeStatement(con, "commit");
volatile sig_atomic_t CancelRequested
Definition: cancel.c:59
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6898
int PQputline(PGconn *conn, const char *s)
Definition: fe-exec.c:2854
int PQendcopy(PGconn *conn)
Definition: fe-exec.c:2885
int j
Definition: isn.c:74
@ PGRES_COPY_IN
Definition: libpq-fe.h:104
#define ntellers
Definition: pgbench.c:257
static void initTruncateTables(PGconn *con)
Definition: pgbench.c:4829
#define LOG_STEP_SECONDS
Definition: pgbench.c:178
#define nbranches
Definition: pgbench.c:256
bool use_quiet
Definition: pgbench.c:270

References CancelRequested, PQExpBufferData::data, executeStatement(), fprintf, i, initPQExpBuffer(), initTruncateTables(), INT64_FORMAT, j, LOG_STEP_SECONDS, naccounts, nbranches, ntellers, partitions, pg_fatal, PG_TIME_GET_DOUBLE, pg_time_now(), PGRES_COPY_IN, PQclear(), PQendcopy(), PQerrorMessage(), PQexec(), PQputline(), PQresultStatus(), PQserverVersion(), printfPQExpBuffer(), res, scale, termPQExpBuffer(), and use_quiet.

Referenced by runInitSteps().

◆ initGenerateDataServerSide()

static void initGenerateDataServerSide ( PGconn con)
static

Definition at line 4978 of file pgbench.c.

4980 {
4981  PQExpBufferData sql;
4982 
4983  fprintf(stderr, "generating data (server-side)...\n");
4984 
4985  /*
4986  * we do all of this in one transaction to enable the backend's
4987  * data-loading optimizations
4988  */
4989  executeStatement(con, "begin");
4990 
4991  /* truncate away any old data */
4992  initTruncateTables(con);
4993 
4994  initPQExpBuffer(&sql);
4995 
4996  printfPQExpBuffer(&sql,
4997  "insert into pgbench_branches(bid,bbalance) "
4998  "select bid, 0 "
4999  "from generate_series(1, %d) as bid", nbranches * scale);
5000  executeStatement(con, sql.data);
5001 
5002  printfPQExpBuffer(&sql,
5003  "insert into pgbench_tellers(tid,bid,tbalance) "
5004  "select tid, (tid - 1) / %d + 1, 0 "
5005  "from generate_series(1, %d) as tid", ntellers, ntellers * scale);
5006  executeStatement(con, sql.data);
5007 
5008  printfPQExpBuffer(&sql,
5009  "insert into pgbench_accounts(aid,bid,abalance,filler) "
5010  "select aid, (aid - 1) / %d + 1, 0, '' "
5011  "from generate_series(1, " INT64_FORMAT ") as aid",
5012  naccounts, (int64) naccounts * scale);
5013  executeStatement(con, sql.data);
5014 
5015  termPQExpBuffer(&sql);
5016 
5017  executeStatement(con, "commit");

References PQExpBufferData::data, executeStatement(), fprintf, initPQExpBuffer(), initTruncateTables(), INT64_FORMAT, naccounts, nbranches, ntellers, printfPQExpBuffer(), scale, and termPQExpBuffer().

Referenced by runInitSteps().

◆ initRandomState()