PostgreSQL Source Code  git master
pgbench.c File Reference
#include "postgres_fe.h"
#include "fe_utils/conditional.h"
#include "getopt_long.h"
#include "libpq-fe.h"
#include "portability/instr_time.h"
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <signal.h>
#include <time.h>
#include "pgbench.h"
Include dependency graph for pgbench.c:

Go to the source code of this file.

Data Structures

struct  Variable
 
struct  SimpleStats
 
struct  StatsData
 
struct  CState
 
struct  ZipfCell
 
struct  ZipfCache
 
struct  TState
 
struct  Command
 
struct  ParsedScript
 
struct  BuiltinScript
 

Macros

#define M_PI   3.14159265358979323846
 
#define ERRCODE_UNDEFINED_TABLE   "42P01"
 
#define FNV_PRIME   UINT64CONST(0x100000001b3)
 
#define FNV_OFFSET_BASIS   UINT64CONST(0xcbf29ce484222325)
 
#define MM2_MUL   UINT64CONST(0xc6a4a7935bd1e995)
 
#define MM2_ROT   47
 
#define pthread_t   void *
 
#define MAXCLIENTS   1024
 
#define DEFAULT_INIT_STEPS   "dtgvp" /* default -I setting */
 
#define LOG_STEP_SECONDS   5 /* seconds between log messages */
 
#define DEFAULT_NXACTS   10 /* default nxacts */
 
#define ZIPF_CACHE_SIZE   15 /* cache cells number */
 
#define MIN_GAUSSIAN_PARAM   2.0 /* minimum parameter for gauss */
 
#define MAX_ZIPFIAN_PARAM   1000 /* maximum parameter for zipfian */
 
#define nbranches
 
#define ntellers   10
 
#define naccounts   100000
 
#define SCALE_32BIT_THRESHOLD   20000
 
#define WSEP   '@' /* weight separator */
 
#define MAX_SCRIPTS   128 /* max number of SQL scripts allowed */
 
#define SHELL_COMMAND_SIZE   256 /* maximum size allowed for shell command */
 
#define INVALID_THREAD   ((pthread_t) 0)
 
#define SQL_COMMAND   1
 
#define META_COMMAND   2
 
#define MAX_ARGS   10
 
#define PARAMS_ARRAY_SIZE   7
 
#define MAX_FARGS   16
 
#define MAX_PREPARE_NAME   32
 
#define SCALE_32BIT_THRESHOLD   20000
 
#define COMMANDS_ALLOC_NUM   128
 

Typedefs

typedef struct SimpleStats SimpleStats
 
typedef struct StatsData StatsData
 
typedef enum MetaCommand MetaCommand
 
typedef enum QueryMode QueryMode
 
typedef struct ParsedScript ParsedScript
 
typedef struct BuiltinScript BuiltinScript
 

Enumerations

enum  ConnectionStateEnum {
  CSTATE_CHOOSE_SCRIPT, CSTATE_START_THROTTLE, CSTATE_THROTTLE, CSTATE_START_TX,
  CSTATE_START_COMMAND, CSTATE_SKIP_COMMAND, CSTATE_WAIT_RESULT, CSTATE_SLEEP,
  CSTATE_END_COMMAND, CSTATE_END_TX, CSTATE_ABORTED, CSTATE_FINISHED
}
 
enum  MetaCommand {
  META_NONE, META_SET, META_SETSHELL, META_SHELL,
  META_SLEEP, META_IF, META_ELIF, META_ELSE,
  META_ENDIF
}
 
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 (TState *, CState *, PgBenchExpr *, PgBenchValue *)
 
static void doLog (TState *thread, CState *st, StatsData *agg, bool skipped, double latency, double lag)
 
static void processXactStats (TState *thread, CState *st, instr_time *now, bool skipped, StatsData *agg)
 
static void pgbench_error (const char *fmt,...) pg_attribute_printf(1
 
static void static void addScript (ParsedScript script)
 
static void * threadRun (void *arg)
 
static void setalarm (int seconds)
 
static void finishCon (CState *st)
 
static void usage (void)
 
static bool is_an_int (const char *str)
 
int64 strtoint64 (const char *str)
 
static int64 getrand (TState *thread, int64 min, int64 max)
 
static int64 getExponentialRand (TState *thread, int64 min, int64 max, double parameter)
 
static int64 getGaussianRand (TState *thread, int64 min, int64 max, double parameter)
 
static int64 getPoissonRand (TState *thread, int64 center)
 
static double generalizedHarmonicNumber (int64 n, double s)
 
static void zipfSetCacheCell (ZipfCell *cell, int64 n, double s)
 
static ZipfCellzipfFindOrCreateCacheCell (ZipfCache *cache, int64 n, double s)
 
static int64 computeIterativeZipfian (TState *thread, int64 n, double s)
 
static int64 computeHarmonicZipfian (TState *thread, int64 n, double s)
 
static int64 getZipfianRand (TState *thread, int64 min, int64 max, double s)
 
static int64 getHashFnv1a (int64 val, uint64 seed)
 
static int64 getHashMurmur2 (int64 val, uint64 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, time_t start_time)
 
static void accumStats (StatsData *stats, bool skipped, double lat, double lag)
 
static void executeStatement (PGconn *con, const char *sql)
 
static void tryExecuteStatement (PGconn *con, const char *sql)
 
static PGconndoConnect (void)
 
static void discard_response (CState *state)
 
static int compareVariableNames (const void *v1, const void *v2)
 
static VariablelookupVariable (CState *st, char *name)
 
static char * getVariable (CState *st, char *name)
 
static bool makeVariableValue (Variable *var)
 
static bool valid_variable_name (const char *name)
 
static VariablelookupCreateVariable (CState *st, const char *context, char *name)
 
static bool putVariable (CState *st, const char *context, char *name, const char *value)
 
static bool putVariableValue (CState *st, const char *context, char *name, const PgBenchValue *value)
 
static bool putVariableInt (CState *st, 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 (CState *st, char *sql)
 
static void getQueryParams (CState *st, 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 (TState *thread, CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
 
static bool evalStandardFunc (TState *thread, CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
 
static bool evalFunc (TState *thread, CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
 
static MetaCommand getMetaCommand (const char *cmd)
 
static bool runShellCommand (CState *st, 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 int chooseScript (TState *thread)
 
static bool sendCommand (CState *st, Command *command)
 
static bool evaluateSleep (CState *st, int argc, char **argv, int *usecs)
 
static void doCustom (TState *thread, CState *st, StatsData *agg)
 
static void disconnect_all (CState *state, int length)
 
static void initDropTables (PGconn *con)
 
static void initCreateTables (PGconn *con)
 
static void initGenerateData (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 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 Commandprocess_sql_command (PQExpBuffer buf, const char *source)
 
static Commandprocess_backslash_command (PsqlScanState sstate, const char *source)
 
static void ConditionError (const char *desc, int cmdn, const char *msg)
 
static void CheckConditional (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 printSimpleStats (const char *prefix, SimpleStats *ss)
 
static void printResults (TState *threads, StatsData *total, instr_time total_time, instr_time conn_total_time, 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
 
int64 throttle_delay = 0
 
int64 latency_limit = 0
 
char * tablespace = NULL
 
char * index_tablespace = NULL
 
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 is_latencies
 
int main_pid
 
char * pghost = ""
 
char * pgport = ""
 
char * login = NULL
 
char * dbName
 
char * logfile_prefix = NULL
 
const char * progname
 
volatile bool timer_exceeded = false
 
static QueryMode querymode = QUERY_SIMPLE
 
static const char * QUERYMODE [] = {"simple", "extended", "prepared"}
 
static ParsedScript sql_script [MAX_SCRIPTS]
 
static int num_scripts
 
static int num_commands = 0
 
static int64 total_weight = 0
 
static int debug = 0
 
static const BuiltinScript builtin_script []
 
static const PsqlScanCallbacks pgbench_callbacks
 

Macro Definition Documentation

◆ COMMANDS_ALLOC_NUM

#define COMMANDS_ALLOC_NUM   128

Referenced by ParseScript().

◆ DEFAULT_INIT_STEPS

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

Definition at line 102 of file pgbench.c.

Referenced by main().

◆ DEFAULT_NXACTS

#define DEFAULT_NXACTS   10 /* default nxacts */

Definition at line 105 of file pgbench.c.

Referenced by main().

◆ ERRCODE_UNDEFINED_TABLE

◆ FNV_OFFSET_BASIS

#define FNV_OFFSET_BASIS   UINT64CONST(0xcbf29ce484222325)

Definition at line 68 of file pgbench.c.

Referenced by getHashFnv1a().

◆ FNV_PRIME

#define FNV_PRIME   UINT64CONST(0x100000001b3)

Definition at line 67 of file pgbench.c.

Referenced by getHashFnv1a().

◆ INVALID_THREAD

#define INVALID_THREAD   ((pthread_t) 0)

Definition at line 405 of file pgbench.c.

Referenced by main().

◆ LOG_STEP_SECONDS

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

Definition at line 104 of file pgbench.c.

Referenced by initGenerateData().

◆ M_PI

#define M_PI   3.14159265358979323846

Definition at line 57 of file pgbench.c.

Referenced by evalStandardFunc(), and getGaussianRand().

◆ MAX_ARGS

#define MAX_ARGS   10

Definition at line 412 of file pgbench.c.

Referenced by parseQuery(), process_backslash_command(), and sendCommand().

◆ MAX_FARGS

#define MAX_FARGS   16

Definition at line 1794 of file pgbench.c.

Referenced by evalStandardFunc().

◆ MAX_PREPARE_NAME

#define MAX_PREPARE_NAME   32

Definition at line 2516 of file pgbench.c.

Referenced by sendCommand().

◆ MAX_SCRIPTS

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

Definition at line 220 of file pgbench.c.

Referenced by addScript().

◆ MAX_ZIPFIAN_PARAM

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

Definition at line 110 of file pgbench.c.

Referenced by evalStandardFunc(), and getZipfianRand().

◆ MAXCLIENTS

#define MAXCLIENTS   1024

Definition at line 99 of file pgbench.c.

Referenced by main().

◆ META_COMMAND

#define META_COMMAND   2

Definition at line 411 of file pgbench.c.

Referenced by CheckConditional(), doCustom(), and process_backslash_command().

◆ MIN_GAUSSIAN_PARAM

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

Definition at line 109 of file pgbench.c.

Referenced by evalStandardFunc(), and getGaussianRand().

◆ MM2_MUL

#define MM2_MUL   UINT64CONST(0xc6a4a7935bd1e995)

Definition at line 69 of file pgbench.c.

Referenced by getHashMurmur2().

◆ MM2_ROT

#define MM2_ROT   47

Definition at line 70 of file pgbench.c.

Referenced by getHashMurmur2().

◆ naccounts

#define naccounts   100000

Definition at line 168 of file pgbench.c.

Referenced by initGenerateData().

◆ nbranches

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

Definition at line 165 of file pgbench.c.

Referenced by initGenerateData().

◆ ntellers

#define ntellers   10

Definition at line 167 of file pgbench.c.

Referenced by initGenerateData().

◆ PARAMS_ARRAY_SIZE

#define PARAMS_ARRAY_SIZE   7

Referenced by doConnect().

◆ pthread_t

#define pthread_t   void *

Definition at line 88 of file pgbench.c.

Referenced by main(), and setalarm().

◆ SCALE_32BIT_THRESHOLD [1/2]

#define SCALE_32BIT_THRESHOLD   20000

Definition at line 177 of file pgbench.c.

Referenced by initCreateTables().

◆ SCALE_32BIT_THRESHOLD [2/2]

#define SCALE_32BIT_THRESHOLD   20000

Definition at line 177 of file pgbench.c.

◆ SHELL_COMMAND_SIZE

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

Definition at line 221 of file pgbench.c.

Referenced by runShellCommand().

◆ SQL_COMMAND

#define SQL_COMMAND   1

Definition at line 410 of file pgbench.c.

Referenced by doCustom(), main(), process_sql_command(), and sendCommand().

◆ WSEP

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

Definition at line 199 of file pgbench.c.

Referenced by parseScriptWeight().

◆ ZIPF_CACHE_SIZE

#define ZIPF_CACHE_SIZE   15 /* cache cells number */

Definition at line 107 of file pgbench.c.

Referenced by zipfFindOrCreateCacheCell().

Typedef Documentation

◆ BuiltinScript

◆ MetaCommand

◆ ParsedScript

◆ QueryMode

◆ SimpleStats

◆ StatsData

Enumeration Type Documentation

◆ ConnectionStateEnum

Enumerator
CSTATE_CHOOSE_SCRIPT 
CSTATE_START_THROTTLE 
CSTATE_THROTTLE 
CSTATE_START_TX 
CSTATE_START_COMMAND 
CSTATE_SKIP_COMMAND 
CSTATE_WAIT_RESULT 
CSTATE_SLEEP 
CSTATE_END_COMMAND 
CSTATE_END_TX 
CSTATE_ABORTED 
CSTATE_FINISHED 

Definition at line 255 of file pgbench.c.

256 {
257  /*
258  * The client must first choose a script to execute. Once chosen, it can
259  * either be throttled (state CSTATE_START_THROTTLE under --rate) or start
260  * right away (state CSTATE_START_TX).
261  */
263 
264  /*
265  * In CSTATE_START_THROTTLE state, we calculate when to begin the next
266  * transaction, and advance to CSTATE_THROTTLE. CSTATE_THROTTLE state
267  * sleeps until that moment. (If throttling is not enabled, doCustom()
268  * falls directly through from CSTATE_START_THROTTLE to CSTATE_START_TX.)
269  */
272 
273  /*
274  * CSTATE_START_TX performs start-of-transaction processing. Establishes
275  * a new connection for the transaction, in --connect mode, and records
276  * the transaction start time.
277  */
279 
280  /*
281  * We loop through these states, to process each command in the script:
282  *
283  * CSTATE_START_COMMAND starts the execution of a command. On a SQL
284  * command, the command is sent to the server, and we move to
285  * CSTATE_WAIT_RESULT state. On a \sleep meta-command, the timer is set,
286  * and we enter the CSTATE_SLEEP state to wait for it to expire. Other
287  * meta-commands are executed immediately.
288  *
289  * CSTATE_SKIP_COMMAND for conditional branches which are not executed,
290  * quickly skip commands that do not need any evaluation.
291  *
292  * CSTATE_WAIT_RESULT waits until we get a result set back from the server
293  * for the current command.
294  *
295  * CSTATE_SLEEP waits until the end of \sleep.
296  *
297  * CSTATE_END_COMMAND records the end-of-command timestamp, increments the
298  * command counter, and loops back to CSTATE_START_COMMAND state.
299  */
303  CSTATE_SLEEP,
305 
306  /*
307  * CSTATE_END_TX performs end-of-transaction processing. Calculates
308  * latency, and logs the transaction. In --connect mode, closes the
309  * current connection. Chooses the next script to execute and starts over
310  * in CSTATE_START_THROTTLE state, or enters CSTATE_FINISHED if we have no
311  * more work to do.
312  */
314 
315  /*
316  * Final states. CSTATE_ABORTED means that the script execution was
317  * aborted because a command failed, CSTATE_FINISHED means success.
318  */
ConnectionStateEnum
Definition: pgbench.c:255

◆ MetaCommand

Enumerator
META_NONE 
META_SET 
META_SETSHELL 
META_SHELL 
META_SLEEP 
META_IF 
META_ELIF 
META_ELSE 
META_ENDIF 

Definition at line 414 of file pgbench.c.

415 {
416  META_NONE, /* not a known meta-command */
417  META_SET, /* \set */
418  META_SETSHELL, /* \setshell */
419  META_SHELL, /* \shell */
420  META_SLEEP, /* \sleep */
421  META_IF, /* \if */
422  META_ELIF, /* \elif */
423  META_ELSE, /* \else */
424  META_ENDIF /* \endif */
425 } MetaCommand;
MetaCommand
Definition: pgbench.c:414

◆ QueryMode

enum QueryMode
Enumerator
QUERY_SIMPLE 
QUERY_EXTENDED 
QUERY_PREPARED 
NUM_QUERYMODE 

Definition at line 427 of file pgbench.c.

428 {
429  QUERY_SIMPLE, /* simple query */
430  QUERY_EXTENDED, /* extended query */
431  QUERY_PREPARED, /* extended query with prepared statements */
433 } QueryMode;
QueryMode
Definition: pgbench.c:427

Function Documentation

◆ accumStats()

static void accumStats ( StatsData stats,
bool  skipped,
double  lat,
double  lag 
)
static

Definition at line 1045 of file pgbench.c.

References addToSimpleStats(), StatsData::cnt, StatsData::lag, StatsData::latency, and StatsData::skipped.

Referenced by doLog(), and processXactStats().

1046 {
1047  stats->cnt++;
1048 
1049  if (skipped)
1050  {
1051  /* no latency to record on skipped transactions */
1052  stats->skipped++;
1053  }
1054  else
1055  {
1056  addToSimpleStats(&stats->latency, lat);
1057 
1058  /* and possibly the same for schedule lag */
1059  if (throttle_delay)
1060  addToSimpleStats(&stats->lag, lag);
1061  }
1062 }
SimpleStats lag
Definition: pgbench.c:249
static void addToSimpleStats(SimpleStats *ss, double val)
Definition: pgbench.c:1001
SimpleStats latency
Definition: pgbench.c:248
int64 cnt
Definition: pgbench.c:245
int64 skipped
Definition: pgbench.c:246
int64 throttle_delay
Definition: pgbench.c:142

◆ addScript()

static void addScript ( ParsedScript  script)
static

Definition at line 4497 of file pgbench.c.

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

Referenced by ParseScript().

4498 {
4499  if (script.commands == NULL || script.commands[0] == NULL)
4500  {
4501  fprintf(stderr, "empty command list for script \"%s\"\n", script.desc);
4502  exit(1);
4503  }
4504 
4505  if (num_scripts >= MAX_SCRIPTS)
4506  {
4507  fprintf(stderr, "at most %d SQL scripts are allowed\n", MAX_SCRIPTS);
4508  exit(1);
4509  }
4510 
4511  CheckConditional(script);
4512 
4513  sql_script[num_scripts] = script;
4514  num_scripts++;
4515 }
static int num_scripts
Definition: pgbench.c:459
#define MAX_SCRIPTS
Definition: pgbench.c:220
static void CheckConditional(ParsedScript ps)
Definition: pgbench.c:4183
const char * desc
Definition: pgbench.c:452
static ParsedScript sql_script[MAX_SCRIPTS]
Definition: pgbench.c:458
Command ** commands
Definition: pgbench.c:454

◆ addToSimpleStats()

static void addToSimpleStats ( SimpleStats ss,
double  val 
)
static

Definition at line 1001 of file pgbench.c.

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

Referenced by accumStats(), and doCustom().

1002 {
1003  if (ss->count == 0 || val < ss->min)
1004  ss->min = val;
1005  if (ss->count == 0 || val > ss->max)
1006  ss->max = val;
1007  ss->count++;
1008  ss->sum += val;
1009  ss->sum2 += val * val;
1010 }
double sum
Definition: pgbench.c:234
int64 count
Definition: pgbench.c:231
double max
Definition: pgbench.c:233
double sum2
Definition: pgbench.c:235
long val
Definition: informix.c:689
double min
Definition: pgbench.c:232

◆ assignVariables()

static char* assignVariables ( CState st,
char *  sql 
)
static

Definition at line 1492 of file pgbench.c.

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

Referenced by sendCommand().

1493 {
1494  char *p,
1495  *name,
1496  *val;
1497 
1498  p = sql;
1499  while ((p = strchr(p, ':')) != NULL)
1500  {
1501  int eaten;
1502 
1503  name = parseVariable(p, &eaten);
1504  if (name == NULL)
1505  {
1506  while (*p == ':')
1507  {
1508  p++;
1509  }
1510  continue;
1511  }
1512 
1513  val = getVariable(st, name);
1514  free(name);
1515  if (val == NULL)
1516  {
1517  p++;
1518  continue;
1519  }
1520 
1521  p = replaceVariable(&sql, p, eaten, val);
1522  }
1523 
1524  return sql;
1525 }
static char * getVariable(CState *st, char *name)
Definition: pgbench.c:1214
static char * replaceVariable(char **sql, char *param, int len, char *value)
Definition: pgbench.c:1472
#define free(a)
Definition: header.h:65
static char * parseVariable(const char *sql, int *eaten)
Definition: pgbench.c:1449
const char * name
Definition: encode.c:521
long val
Definition: informix.c:689

◆ CheckConditional()

static void CheckConditional ( ParsedScript  ps)
static

Definition at line 4183 of file pgbench.c.

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().

4184 {
4185  /* statically check conditional structure */
4187  int i;
4188  for (i = 0 ; ps.commands[i] != NULL ; i++)
4189  {
4190  Command *cmd = ps.commands[i];
4191  if (cmd->type == META_COMMAND)
4192  {
4193  switch (cmd->meta)
4194  {
4195  case META_IF:
4197  break;
4198  case META_ELIF:
4199  if (conditional_stack_empty(cs))
4200  ConditionError(ps.desc, i+1, "\\elif without matching \\if");
4202  ConditionError(ps.desc, i+1, "\\elif after \\else");
4203  break;
4204  case META_ELSE:
4205  if (conditional_stack_empty(cs))
4206  ConditionError(ps.desc, i+1, "\\else without matching \\if");
4208  ConditionError(ps.desc, i+1, "\\else after \\else");
4210  break;
4211  case META_ENDIF:
4212  if (!conditional_stack_pop(cs))
4213  ConditionError(ps.desc, i+1, "\\endif without matching \\if");
4214  break;
4215  default:
4216  /* ignore anything else... */
4217  break;
4218  }
4219  }
4220  }
4221  if (!conditional_stack_empty(cs))
4222  ConditionError(ps.desc, i+1, "\\if without matching \\endif");
4224 }
int type
Definition: pgbench.c:442
bool conditional_stack_pop(ConditionalStack cstack)
Definition: conditional.c:57
static void ConditionError(const char *desc, int cmdn, const char *msg)
Definition: pgbench.c:4171
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:41
#define META_COMMAND
Definition: pgbench.c:411
const char * desc
Definition: pgbench.c:452
MetaCommand meta
Definition: pgbench.c:443
ConditionalStack conditional_stack_create(void)
Definition: conditional.c:18
ifState conditional_stack_peek(ConditionalStack cstack)
Definition: conditional.c:93
bool conditional_stack_poke(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:105
Command ** commands
Definition: pgbench.c:454
void conditional_stack_destroy(ConditionalStack cstack)
Definition: conditional.c:30
bool conditional_stack_empty(ConditionalStack cstack)
Definition: conditional.c:117
int i

◆ checkInitSteps()

static void checkInitSteps ( const char *  initialize_steps)
static

Definition at line 3751 of file pgbench.c.

Referenced by main().

3752 {
3753  const char *step;
3754 
3755  if (initialize_steps[0] == '\0')
3756  {
3757  fprintf(stderr, "no initialization steps specified\n");
3758  exit(1);
3759  }
3760 
3761  for (step = initialize_steps; *step != '\0'; step++)
3762  {
3763  if (strchr("dtgvpf ", *step) == NULL)
3764  {
3765  fprintf(stderr, "unrecognized initialization step \"%c\"\n",
3766  *step);
3767  fprintf(stderr, "allowed steps are: \"d\", \"t\", \"g\", \"v\", \"p\", \"f\"\n");
3768  exit(1);
3769  }
3770  }
3771 }

◆ chooseScript()

static int chooseScript ( TState thread)
static

Definition at line 2533 of file pgbench.c.

References getrand(), i, and ParsedScript::weight.

Referenced by doCustom().

2534 {
2535  int i = 0;
2536  int64 w;
2537 
2538  if (num_scripts == 1)
2539  return 0;
2540 
2541  w = getrand(thread, 0, total_weight - 1);
2542  do
2543  {
2544  w -= sql_script[i++].weight;
2545  } while (w >= 0);
2546 
2547  return i - 1;
2548 }
static int64 getrand(TState *thread, int64 min, int64 max)
Definition: pgbench.c:696
static int num_scripts
Definition: pgbench.c:459
int weight
Definition: pgbench.c:453
static ParsedScript sql_script[MAX_SCRIPTS]
Definition: pgbench.c:458
static int64 total_weight
Definition: pgbench.c:461
int i

◆ coerceToBool()

static bool coerceToBool ( PgBenchValue pval,
bool bval 
)
static

Definition at line 1559 of file pgbench.c.

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

Referenced by evalLazyFunc(), and evalStandardFunc().

1560 {
1561  if (pval->type == PGBT_BOOLEAN)
1562  {
1563  *bval = pval->u.bval;
1564  return true;
1565  }
1566  else /* NULL, INT or DOUBLE */
1567  {
1568  fprintf(stderr, "cannot coerce %s to boolean\n", valueTypeName(pval));
1569  *bval = false; /* suppress uninitialized-variable warnings */
1570  return false;
1571  }
1572 }
union PgBenchValue::@39 u
static char * valueTypeName(PgBenchValue *pval)
Definition: pgbench.c:1537
bool bval
Definition: pgbench.h:51
PgBenchValueType type
Definition: pgbench.h:46

◆ coerceToDouble()

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

Definition at line 1628 of file pgbench.c.

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

Referenced by evalStandardFunc().

1629 {
1630  if (pval->type == PGBT_DOUBLE)
1631  {
1632  *dval = pval->u.dval;
1633  return true;
1634  }
1635  else if (pval->type == PGBT_INT)
1636  {
1637  *dval = (double) pval->u.ival;
1638  return true;
1639  }
1640  else /* BOOLEAN or NULL */
1641  {
1642  fprintf(stderr, "cannot coerce %s to double\n", valueTypeName(pval));
1643  return false;
1644  }
1645 }
union PgBenchValue::@39 u
static char * valueTypeName(PgBenchValue *pval)
Definition: pgbench.c:1537
double dval
Definition: pgbench.h:50
PgBenchValueType type
Definition: pgbench.h:46
int64 ival
Definition: pgbench.h:49

◆ coerceToInt()

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

Definition at line 1600 of file pgbench.c.

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

Referenced by evalStandardFunc().

1601 {
1602  if (pval->type == PGBT_INT)
1603  {
1604  *ival = pval->u.ival;
1605  return true;
1606  }
1607  else if (pval->type == PGBT_DOUBLE)
1608  {
1609  double dval = pval->u.dval;
1610 
1611  if (dval < PG_INT64_MIN || PG_INT64_MAX < dval)
1612  {
1613  fprintf(stderr, "double to int overflow for %f\n", dval);
1614  return false;
1615  }
1616  *ival = (int64) dval;
1617  return true;
1618  }
1619  else /* BOOLEAN or NULL */
1620  {
1621  fprintf(stderr, "cannot coerce %s to int\n", valueTypeName(pval));
1622  return false;
1623  }
1624 }
#define PG_INT64_MAX
Definition: c.h:411
union PgBenchValue::@39 u
static char * valueTypeName(PgBenchValue *pval)
Definition: pgbench.c:1537
#define PG_INT64_MIN
Definition: c.h:410
double dval
Definition: pgbench.h:50
PgBenchValueType type
Definition: pgbench.h:46
int64 ival
Definition: pgbench.h:49

◆ commandFailed()

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

Definition at line 2524 of file pgbench.c.

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

Referenced by doCustom().

2525 {
2526  fprintf(stderr,
2527  "client %d aborted in command %d (%s) of script %d; %s\n",
2528  st->id, st->command, cmd, st->use_file, message);
2529 }
int id
Definition: pgbench.c:329
int command
Definition: pgbench.c:334
int use_file
Definition: pgbench.c:333

◆ compareVariableNames()

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

Definition at line 1179 of file pgbench.c.

References name.

Referenced by lookupVariable().

1180 {
1181  return strcmp(((const Variable *) v1)->name,
1182  ((const Variable *) v2)->name);
1183 }
const char * name
Definition: encode.c:521

◆ computeHarmonicZipfian()

static int64 computeHarmonicZipfian ( TState thread,
int64  n,
double  s 
)
static

Definition at line 912 of file pgbench.c.

References ZipfCell::alpha, ZipfCell::eta, ZipfCell::harmonicn, ZipfCell::n, pg_erand48(), TState::random_state, TState::zipf_cache, and zipfFindOrCreateCacheCell().

Referenced by getZipfianRand().

913 {
914  ZipfCell *cell = zipfFindOrCreateCacheCell(&thread->zipf_cache, n, s);
915  double uniform = pg_erand48(thread->random_state);
916  double uz = uniform * cell->harmonicn;
917 
918  if (uz < 1.0)
919  return 1;
920  if (uz < 1.0 + cell->beta)
921  return 2;
922  return 1 + (int64) (cell->n * pow(cell->eta * uniform - cell->eta + 1.0, cell->alpha));
923 }
double harmonicn
Definition: pgbench.c:363
double alpha
Definition: pgbench.c:364
unsigned short random_state[3]
Definition: pgbench.c:392
int64 n
Definition: pgbench.c:361
static ZipfCell * zipfFindOrCreateCacheCell(ZipfCache *cache, int64 n, double s)
Definition: pgbench.c:843
ZipfCache zipf_cache
Definition: pgbench.c:395
double pg_erand48(unsigned short xseed[3])
Definition: erand48.c:79
double eta
Definition: pgbench.c:366

◆ computeIterativeZipfian()

static int64 computeIterativeZipfian ( TState thread,
int64  n,
double  s 
)
static

Definition at line 882 of file pgbench.c.

References pg_erand48(), and TState::random_state.

Referenced by getZipfianRand().

883 {
884  double b = pow(2.0, s - 1.0);
885  double x,
886  t,
887  u,
888  v;
889 
890  while (true)
891  {
892  /* random variates */
893  u = pg_erand48(thread->random_state);
894  v = pg_erand48(thread->random_state);
895 
896  x = floor(pow(u, -1.0 / (s - 1.0)));
897 
898  t = pow(1.0 + 1.0 / x, s - 1.0);
899  /* reject if too large or out of bound */
900  if (v * x * (t - 1.0) / (b - 1.0) <= t / b && x <= n)
901  break;
902  }
903  return (int64) x;
904 }
unsigned short random_state[3]
Definition: pgbench.c:392
double pg_erand48(unsigned short xseed[3])
Definition: erand48.c:79

◆ ConditionError()

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

Definition at line 4171 of file pgbench.c.

Referenced by CheckConditional().

4172 {
4173  fprintf(stderr,
4174  "condition error in script \"%s\" command %d: %s\n",
4175  desc, cmdn, msg);
4176  exit(1);
4177 }

◆ discard_response()

static void discard_response ( CState state)
static

Definition at line 1165 of file pgbench.c.

References CState::con, PQclear(), and PQgetResult().

Referenced by doCustom().

1166 {
1167  PGresult *res;
1168 
1169  do
1170  {
1171  res = PQgetResult(state->con);
1172  if (res)
1173  PQclear(res);
1174  } while (res);
1175 }
void PQclear(PGresult *res)
Definition: fe-exec.c:671
PGconn * con
Definition: pgbench.c:328
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753

◆ disconnect_all()

static void disconnect_all ( CState state,
int  length 
)
static

Definition at line 3411 of file pgbench.c.

References finishCon(), i, and length().

Referenced by main(), and threadRun().

3412 {
3413  int i;
3414 
3415  for (i = 0; i < length; i++)
3416  finishCon(&state[i]);
3417 }
int length(const List *list)
Definition: list.c:1333
static void finishCon(CState *st)
Definition: pgbench.c:5940
int i

◆ doConnect()

static PGconn* doConnect ( void  )
static

Definition at line 1096 of file pgbench.c.

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

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

1097 {
1098  PGconn *conn;
1099  bool new_pass;
1100  static bool have_password = false;
1101  static char password[100];
1102 
1103  /*
1104  * Start the connection. Loop until we have a password if requested by
1105  * backend.
1106  */
1107  do
1108  {
1109 #define PARAMS_ARRAY_SIZE 7
1110 
1111  const char *keywords[PARAMS_ARRAY_SIZE];
1112  const char *values[PARAMS_ARRAY_SIZE];
1113 
1114  keywords[0] = "host";
1115  values[0] = pghost;
1116  keywords[1] = "port";
1117  values[1] = pgport;
1118  keywords[2] = "user";
1119  values[2] = login;
1120  keywords[3] = "password";
1121  values[3] = have_password ? password : NULL;
1122  keywords[4] = "dbname";
1123  values[4] = dbName;
1124  keywords[5] = "fallback_application_name";
1125  values[5] = progname;
1126  keywords[6] = NULL;
1127  values[6] = NULL;
1128 
1129  new_pass = false;
1130 
1131  conn = PQconnectdbParams(keywords, values, true);
1132 
1133  if (!conn)
1134  {
1135  fprintf(stderr, "connection to database \"%s\" failed\n",
1136  dbName);
1137  return NULL;
1138  }
1139 
1140  if (PQstatus(conn) == CONNECTION_BAD &&
1141  PQconnectionNeedsPassword(conn) &&
1142  !have_password)
1143  {
1144  PQfinish(conn);
1145  simple_prompt("Password: ", password, sizeof(password), false);
1146  have_password = true;
1147  new_pass = true;
1148  }
1149  } while (new_pass);
1150 
1151  /* check to see that the backend connection was successfully made */
1152  if (PQstatus(conn) == CONNECTION_BAD)
1153  {
1154  fprintf(stderr, "connection to database \"%s\" failed:\n%s",
1155  dbName, PQerrorMessage(conn));
1156  PQfinish(conn);
1157  return NULL;
1158  }
1159 
1160  return conn;
1161 }
static char password[100]
Definition: streamutil.c:54
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6116
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3638
PGconn * PQconnectdbParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:536
PGconn * conn
Definition: streamutil.c:55
void simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
Definition: sprompt.c:37
#define PARAMS_ARRAY_SIZE
char * pghost
Definition: pgbench.c:192
static bool have_password
Definition: streamutil.c:53
const char * progname
Definition: pgbench.c:197
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int PQconnectionNeedsPassword(const PGconn *conn)
Definition: fe-connect.c:6150
char * dbName
Definition: pgbench.c:195
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6063
char * pgport
Definition: pgbench.c:193
char * login
Definition: pgbench.c:194

◆ doCustom()

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

Definition at line 2671 of file pgbench.c.

References addToSimpleStats(), Command::argc, Command::argv, Assert, 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(), TState::conn_time, CState::cstack, CSTATE_ABORTED, CSTATE_CHOOSE_SCRIPT, CSTATE_END_COMMAND, CSTATE_END_TX, CSTATE_FINISHED, CSTATE_SKIP_COMMAND, CSTATE_SLEEP, CSTATE_START_COMMAND, CSTATE_START_THROTTLE, CSTATE_START_TX, CSTATE_THROTTLE, CSTATE_WAIT_RESULT, ParsedScript::desc, discard_response(), doConnect(), evaluateExpr(), evaluateSleep(), Command::expr, finishCon(), getPoissonRand(), i, CState::id, IFSTATE_ELSE_FALSE, IFSTATE_ELSE_TRUE, IFSTATE_FALSE, IFSTATE_IGNORED, IFSTATE_NONE, IFSTATE_TRUE, INSTR_TIME_ACCUM_DIFF, INSTR_TIME_GET_DOUBLE, INSTR_TIME_GET_MICROSEC, INSTR_TIME_IS_ZERO, INSTR_TIME_SET_CURRENT, INSTR_TIME_SET_ZERO, INT64_FORMAT, Command::meta, META_COMMAND, META_ELIF, META_ELSE, META_ENDIF, META_IF, META_SET, META_SETSHELL, META_SHELL, META_SLEEP, now(), PGRES_COMMAND_OK, PGRES_EMPTY_QUERY, PGRES_TUPLES_OK, PQclear(), PQconsumeInput(), PQerrorMessage(), PQgetResult(), PQisBusy(), PQresultStatus(), CState::prepared, processXactStats(), putVariableValue(), runShellCommand(), sendCommand(), CState::sleep_until, SQL_COMMAND, CState::state, Command::stats, CState::stmt_begin, TState::throttle_trigger, CState::txn_begin, CState::txn_scheduled, Command::type, CState::use_file, and valueTruth().

Referenced by threadRun().

2672 {
2673  PGresult *res;
2674  Command *command;
2675  instr_time now;
2676  bool end_tx_processed = false;
2677  int64 wait;
2678 
2679  /*
2680  * gettimeofday() isn't free, so we get the current timestamp lazily the
2681  * first time it's needed, and reuse the same value throughout this
2682  * function after that. This also ensures that e.g. the calculated
2683  * latency reported in the log file and in the totals are the same. Zero
2684  * means "not set yet". Reset "now" when we execute shell commands or
2685  * expressions, which might take a non-negligible amount of time, though.
2686  */
2687  INSTR_TIME_SET_ZERO(now);
2688 
2689  /*
2690  * Loop in the state machine, until we have to wait for a result from the
2691  * server (or have to sleep, for throttling or for \sleep).
2692  *
2693  * Note: In the switch-statement below, 'break' will loop back here,
2694  * meaning "continue in the state machine". Return is used to return to
2695  * the caller.
2696  */
2697  for (;;)
2698  {
2699  switch (st->state)
2700  {
2701  /*
2702  * Select transaction to run.
2703  */
2704  case CSTATE_CHOOSE_SCRIPT:
2705 
2706  st->use_file = chooseScript(thread);
2707 
2708  if (debug)
2709  fprintf(stderr, "client %d executing script \"%s\"\n", st->id,
2710  sql_script[st->use_file].desc);
2711 
2712  if (throttle_delay > 0)
2714  else
2715  st->state = CSTATE_START_TX;
2716  /* check consistency */
2718  break;
2719 
2720  /*
2721  * Handle throttling once per transaction by sleeping.
2722  */
2723  case CSTATE_START_THROTTLE:
2724 
2725  /*
2726  * Generate a delay such that the series of delays will
2727  * approximate a Poisson distribution centered on the
2728  * throttle_delay time.
2729  *
2730  * If transactions are too slow or a given wait is shorter
2731  * than a transaction, the next transaction will start right
2732  * away.
2733  */
2734  Assert(throttle_delay > 0);
2735  wait = getPoissonRand(thread, throttle_delay);
2736 
2737  thread->throttle_trigger += wait;
2738  st->txn_scheduled = thread->throttle_trigger;
2739 
2740  /*
2741  * stop client if next transaction is beyond pgbench end of
2742  * execution
2743  */
2744  if (duration > 0 && st->txn_scheduled > end_time)
2745  {
2746  st->state = CSTATE_FINISHED;
2747  break;
2748  }
2749 
2750  /*
2751  * If --latency-limit is used, and this slot is already late
2752  * so that the transaction will miss the latency limit even if
2753  * it completed immediately, we skip this time slot and
2754  * iterate till the next slot that isn't late yet. But don't
2755  * iterate beyond the -t limit, if one is given.
2756  */
2757  if (latency_limit)
2758  {
2759  int64 now_us;
2760 
2761  if (INSTR_TIME_IS_ZERO(now))
2763  now_us = INSTR_TIME_GET_MICROSEC(now);
2764  while (thread->throttle_trigger < now_us - latency_limit &&
2765  (nxacts <= 0 || st->cnt < nxacts))
2766  {
2767  processXactStats(thread, st, &now, true, agg);
2768  /* next rendez-vous */
2769  wait = getPoissonRand(thread, throttle_delay);
2770  thread->throttle_trigger += wait;
2771  st->txn_scheduled = thread->throttle_trigger;
2772  }
2773  /* stop client if -t exceeded */
2774  if (nxacts > 0 && st->cnt >= nxacts)
2775  {
2776  st->state = CSTATE_FINISHED;
2777  break;
2778  }
2779  }
2780 
2781  st->state = CSTATE_THROTTLE;
2782  if (debug)
2783  fprintf(stderr, "client %d throttling " INT64_FORMAT " us\n",
2784  st->id, wait);
2785  break;
2786 
2787  /*
2788  * Wait until it's time to start next transaction.
2789  */
2790  case CSTATE_THROTTLE:
2791  if (INSTR_TIME_IS_ZERO(now))
2793  if (INSTR_TIME_GET_MICROSEC(now) < st->txn_scheduled)
2794  return; /* Still sleeping, nothing to do here */
2795 
2796  /* Else done sleeping, start the transaction */
2797  st->state = CSTATE_START_TX;
2798  break;
2799 
2800  /* Start new transaction */
2801  case CSTATE_START_TX:
2802 
2803  /*
2804  * Establish connection on first call, or if is_connect is
2805  * true.
2806  */
2807  if (st->con == NULL)
2808  {
2809  instr_time start;
2810 
2811  if (INSTR_TIME_IS_ZERO(now))
2813  start = now;
2814  if ((st->con = doConnect()) == NULL)
2815  {
2816  fprintf(stderr, "client %d aborted while establishing connection\n",
2817  st->id);
2818  st->state = CSTATE_ABORTED;
2819  break;
2820  }
2822  INSTR_TIME_ACCUM_DIFF(thread->conn_time, now, start);
2823 
2824  /* Reset session-local state */
2825  memset(st->prepared, 0, sizeof(st->prepared));
2826  }
2827 
2828  /*
2829  * Record transaction start time under logging, progress or
2830  * throttling.
2831  */
2834  {
2835  if (INSTR_TIME_IS_ZERO(now))
2837  st->txn_begin = now;
2838 
2839  /*
2840  * When not throttling, this is also the transaction's
2841  * scheduled start time.
2842  */
2843  if (!throttle_delay)
2845  }
2846 
2847  /* Begin with the first command */
2848  st->command = 0;
2850  break;
2851 
2852  /*
2853  * Send a command to server (or execute a meta-command)
2854  */
2855  case CSTATE_START_COMMAND:
2856  command = sql_script[st->use_file].commands[st->command];
2857 
2858  /*
2859  * If we reached the end of the script, move to end-of-xact
2860  * processing.
2861  */
2862  if (command == NULL)
2863  {
2864  st->state = CSTATE_END_TX;
2865  break;
2866  }
2867 
2868  /*
2869  * Record statement start time if per-command latencies are
2870  * requested
2871  */
2872  if (is_latencies)
2873  {
2874  if (INSTR_TIME_IS_ZERO(now))
2876  st->stmt_begin = now;
2877  }
2878 
2879  if (command->type == SQL_COMMAND)
2880  {
2881  if (!sendCommand(st, command))
2882  {
2883  commandFailed(st, "SQL", "SQL command send failed");
2884  st->state = CSTATE_ABORTED;
2885  }
2886  else
2887  st->state = CSTATE_WAIT_RESULT;
2888  }
2889  else if (command->type == META_COMMAND)
2890  {
2891  int argc = command->argc,
2892  i;
2893  char **argv = command->argv;
2894 
2895  if (debug)
2896  {
2897  fprintf(stderr, "client %d executing \\%s", st->id, argv[0]);
2898  for (i = 1; i < argc; i++)
2899  fprintf(stderr, " %s", argv[i]);
2900  fprintf(stderr, "\n");
2901  }
2902 
2903  if (command->meta == META_SLEEP)
2904  {
2905  /*
2906  * A \sleep doesn't execute anything, we just get the
2907  * delay from the argument, and enter the CSTATE_SLEEP
2908  * state. (The per-command latency will be recorded
2909  * in CSTATE_SLEEP state, not here, after the delay
2910  * has elapsed.)
2911  */
2912  int usec;
2913 
2914  if (!evaluateSleep(st, argc, argv, &usec))
2915  {
2916  commandFailed(st, "sleep", "execution of meta-command failed");
2917  st->state = CSTATE_ABORTED;
2918  break;
2919  }
2920 
2921  if (INSTR_TIME_IS_ZERO(now))
2923  st->sleep_until = INSTR_TIME_GET_MICROSEC(now) + usec;
2924  st->state = CSTATE_SLEEP;
2925  break;
2926  }
2927  else if (command->meta == META_SET ||
2928  command->meta == META_IF ||
2929  command->meta == META_ELIF)
2930  {
2931  /* backslash commands with an expression to evaluate */
2932  PgBenchExpr *expr = command->expr;
2933  PgBenchValue result;
2934 
2935  if (command->meta == META_ELIF &&
2937  {
2938  /* elif after executed block, skip eval and wait for endif */
2940  goto move_to_end_command;
2941  }
2942 
2943  if (!evaluateExpr(thread, st, expr, &result))
2944  {
2945  commandFailed(st, argv[0], "evaluation of meta-command failed");
2946  st->state = CSTATE_ABORTED;
2947  break;
2948  }
2949 
2950  if (command->meta == META_SET)
2951  {
2952  if (!putVariableValue(st, argv[0], argv[1], &result))
2953  {
2954  commandFailed(st, "set", "assignment of meta-command failed");
2955  st->state = CSTATE_ABORTED;
2956  break;
2957  }
2958  }
2959  else /* if and elif evaluated cases */
2960  {
2961  bool cond = valueTruth(&result);
2962 
2963  /* execute or not depending on evaluated condition */
2964  if (command->meta == META_IF)
2965  {
2967  }
2968  else /* elif */
2969  {
2970  /* we should get here only if the "elif" needed evaluation */
2973  }
2974  }
2975  }
2976  else if (command->meta == META_ELSE)
2977  {
2978  switch (conditional_stack_peek(st->cstack))
2979  {
2980  case IFSTATE_TRUE:
2982  break;
2983  case IFSTATE_FALSE: /* inconsistent if active */
2984  case IFSTATE_IGNORED: /* inconsistent if active */
2985  case IFSTATE_NONE: /* else without if */
2986  case IFSTATE_ELSE_TRUE: /* else after else */
2987  case IFSTATE_ELSE_FALSE: /* else after else */
2988  default:
2989  /* dead code if conditional check is ok */
2990  Assert(false);
2991  }
2992  goto move_to_end_command;
2993  }
2994  else if (command->meta == META_ENDIF)
2995  {
2998  goto move_to_end_command;
2999  }
3000  else if (command->meta == META_SETSHELL)
3001  {
3002  bool ret = runShellCommand(st, argv[1], argv + 2, argc - 2);
3003 
3004  if (timer_exceeded) /* timeout */
3005  {
3006  st->state = CSTATE_FINISHED;
3007  break;
3008  }
3009  else if (!ret) /* on error */
3010  {
3011  commandFailed(st, "setshell", "execution of meta-command failed");
3012  st->state = CSTATE_ABORTED;
3013  break;
3014  }
3015  else
3016  {
3017  /* succeeded */
3018  }
3019  }
3020  else if (command->meta == META_SHELL)
3021  {
3022  bool ret = runShellCommand(st, NULL, argv + 1, argc - 1);
3023 
3024  if (timer_exceeded) /* timeout */
3025  {
3026  st->state = CSTATE_FINISHED;
3027  break;
3028  }
3029  else if (!ret) /* on error */
3030  {
3031  commandFailed(st, "shell", "execution of meta-command failed");
3032  st->state = CSTATE_ABORTED;
3033  break;
3034  }
3035  else
3036  {
3037  /* succeeded */
3038  }
3039  }
3040 
3041  move_to_end_command:
3042  /*
3043  * executing the expression or shell command might
3044  * take a non-negligible amount of time, so reset
3045  * 'now'
3046  */
3047  INSTR_TIME_SET_ZERO(now);
3048 
3049  st->state = CSTATE_END_COMMAND;
3050  }
3051  break;
3052 
3053  /*
3054  * non executed conditional branch
3055  */
3056  case CSTATE_SKIP_COMMAND:
3058  /* quickly skip commands until something to do... */
3059  while (true)
3060  {
3061  command = sql_script[st->use_file].commands[st->command];
3062 
3063  /* cannot reach end of script in that state */
3064  Assert(command != NULL);
3065 
3066  /* if this is conditional related, update conditional state */
3067  if (command->type == META_COMMAND &&
3068  (command->meta == META_IF ||
3069  command->meta == META_ELIF ||
3070  command->meta == META_ELSE ||
3071  command->meta == META_ENDIF))
3072  {
3073  switch (conditional_stack_peek(st->cstack))
3074  {
3075  case IFSTATE_FALSE:
3076  if (command->meta == META_IF || command->meta == META_ELIF)
3077  {
3078  /* we must evaluate the condition */
3080  }
3081  else if (command->meta == META_ELSE)
3082  {
3083  /* we must execute next command */
3086  st->command++;
3087  }
3088  else if (command->meta == META_ENDIF)
3089  {
3092  if (conditional_active(st->cstack))
3094  /* else state remains in CSTATE_SKIP_COMMAND */
3095  st->command++;
3096  }
3097  break;
3098 
3099  case IFSTATE_IGNORED:
3100  case IFSTATE_ELSE_FALSE:
3101  if (command->meta == META_IF)
3103  else if (command->meta == META_ENDIF)
3104  {
3107  if (conditional_active(st->cstack))
3109  }
3110  /* could detect "else" & "elif" after "else" */
3111  st->command++;
3112  break;
3113 
3114  case IFSTATE_NONE:
3115  case IFSTATE_TRUE:
3116  case IFSTATE_ELSE_TRUE:
3117  default:
3118  /* inconsistent if inactive, unreachable dead code */
3119  Assert(false);
3120  }
3121  }
3122  else
3123  {
3124  /* skip and consider next */
3125  st->command++;
3126  }
3127 
3128  if (st->state != CSTATE_SKIP_COMMAND)
3129  break;
3130  }
3131  break;
3132 
3133  /*
3134  * Wait for the current SQL command to complete
3135  */
3136  case CSTATE_WAIT_RESULT:
3137  command = sql_script[st->use_file].commands[st->command];
3138  if (debug)
3139  fprintf(stderr, "client %d receiving\n", st->id);
3140  if (!PQconsumeInput(st->con))
3141  { /* there's something wrong */
3142  commandFailed(st, "SQL", "perhaps the backend died while processing");
3143  st->state = CSTATE_ABORTED;
3144  break;
3145  }
3146  if (PQisBusy(st->con))
3147  return; /* don't have the whole result yet */
3148 
3149  /*
3150  * Read and discard the query result;
3151  */
3152  res = PQgetResult(st->con);
3153  switch (PQresultStatus(res))
3154  {
3155  case PGRES_COMMAND_OK:
3156  case PGRES_TUPLES_OK:
3157  case PGRES_EMPTY_QUERY:
3158  /* OK */
3159  PQclear(res);
3160  discard_response(st);
3161  st->state = CSTATE_END_COMMAND;
3162  break;
3163  default:
3164  commandFailed(st, "SQL", PQerrorMessage(st->con));
3165  PQclear(res);
3166  st->state = CSTATE_ABORTED;
3167  break;
3168  }
3169  break;
3170 
3171  /*
3172  * Wait until sleep is done. This state is entered after a
3173  * \sleep metacommand. The behavior is similar to
3174  * CSTATE_THROTTLE, but proceeds to CSTATE_START_COMMAND
3175  * instead of CSTATE_START_TX.
3176  */
3177  case CSTATE_SLEEP:
3178  if (INSTR_TIME_IS_ZERO(now))
3180  if (INSTR_TIME_GET_MICROSEC(now) < st->sleep_until)
3181  return; /* Still sleeping, nothing to do here */
3182  /* Else done sleeping. */
3183  st->state = CSTATE_END_COMMAND;
3184  break;
3185 
3186  /*
3187  * End of command: record stats and proceed to next command.
3188  */
3189  case CSTATE_END_COMMAND:
3190 
3191  /*
3192  * command completed: accumulate per-command execution times
3193  * in thread-local data structure, if per-command latencies
3194  * are requested.
3195  */
3196  if (is_latencies)
3197  {
3198  if (INSTR_TIME_IS_ZERO(now))
3200 
3201  /* XXX could use a mutex here, but we choose not to */
3202  command = sql_script[st->use_file].commands[st->command];
3203  addToSimpleStats(&command->stats,
3204  INSTR_TIME_GET_DOUBLE(now) -
3206  }
3207 
3208  /* Go ahead with next command, to be executed or skipped */
3209  st->command++;
3210  st->state = conditional_active(st->cstack) ?
3212  break;
3213 
3214  /*
3215  * End of transaction.
3216  */
3217  case CSTATE_END_TX:
3218 
3219  /* transaction finished: calculate latency and do log */
3220  processXactStats(thread, st, &now, false, agg);
3221 
3222  /* conditional stack must be empty */
3223  if (!conditional_stack_empty(st->cstack))
3224  {
3225  fprintf(stderr, "end of script reached within a conditional, missing \\endif\n");
3226  exit(1);
3227  }
3228 
3229  if (is_connect)
3230  {
3231  finishCon(st);
3232  INSTR_TIME_SET_ZERO(now);
3233  }
3234 
3235  if ((st->cnt >= nxacts && duration <= 0) || timer_exceeded)
3236  {
3237  /* exit success */
3238  st->state = CSTATE_FINISHED;
3239  break;
3240  }
3241 
3242  /*
3243  * No transaction is underway anymore.
3244  */
3246 
3247  /*
3248  * If we paced through all commands in the script in this
3249  * loop, without returning to the caller even once, do it now.
3250  * This gives the thread a chance to process other
3251  * connections, and to do progress reporting. This can
3252  * currently only happen if the script consists entirely of
3253  * meta-commands.
3254  */
3255  if (end_tx_processed)
3256  return;
3257  else
3258  {
3259  end_tx_processed = true;
3260  break;
3261  }
3262 
3263  /*
3264  * Final states. Close the connection if it's still open.
3265  */
3266  case CSTATE_ABORTED:
3267  case CSTATE_FINISHED:
3268  finishCon(st);
3269  return;
3270  }
3271  }
3272 }
static bool evaluateExpr(TState *, CState *, PgBenchExpr *, PgBenchValue *)
Definition: pgbench.c:2335
int64 throttle_trigger
Definition: pgbench.c:393
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6116
bool conditional_active(ConditionalStack cstack)
Definition: conditional.c:127
int type
Definition: pgbench.c:442
int id
Definition: pgbench.c:329
static int chooseScript(TState *thread)
Definition: pgbench.c:2533
static void discard_response(CState *state)
Definition: pgbench.c:1165
bool conditional_stack_pop(ConditionalStack cstack)
Definition: conditional.c:57
void conditional_stack_push(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:41
static void commandFailed(CState *st, const char *cmd, const char *message)
Definition: pgbench.c:2524
struct timeval instr_time
Definition: instr_time.h:147
PgBenchExpr * expr
Definition: pgbench.c:446
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:179
static void addToSimpleStats(SimpleStats *ss, double val)
Definition: pgbench.c:1001
#define INSTR_TIME_SET_ZERO(t)
Definition: instr_time.h:151
bool use_log
Definition: pgbench.c:179
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:196
bool per_script_stats
Definition: pgbench.c:183
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
char * argv[MAX_ARGS]
Definition: pgbench.c:445
int duration
Definition: pgbench.c:113
ConditionalStack cstack
Definition: pgbench.c:331
#define INSTR_TIME_IS_ZERO(t)
Definition: instr_time.h:149
static void finishCon(CState *st)
Definition: pgbench.c:5940
bool is_connect
Definition: pgbench.c:188
int64 end_time
Definition: pgbench.c:114
instr_time stmt_begin
Definition: pgbench.c:345
#define META_COMMAND
Definition: pgbench.c:411
static int debug
Definition: pgbench.c:463
int nxacts
Definition: pgbench.c:112
const char * desc
Definition: pgbench.c:452
int64 cnt
Definition: pgbench.c:350
MetaCommand meta
Definition: pgbench.c:443
int64 txn_scheduled
Definition: pgbench.c:342
static ParsedScript sql_script[MAX_SCRIPTS]
Definition: pgbench.c:458
static bool sendCommand(CState *st, Command *command)
Definition: pgbench.c:2552
int progress
Definition: pgbench.c:184
instr_time txn_begin
Definition: pgbench.c:344
int argc
Definition: pgbench.c:444
#define SQL_COMMAND
Definition: pgbench.c:410
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1682
int command
Definition: pgbench.c:334
SimpleStats stats
Definition: pgbench.c:447
ConnectionStateEnum state
Definition: pgbench.c:330
static bool runShellCommand(CState *st, char *variable, char **argv, int argc)
Definition: pgbench.c:2413
ifState conditional_stack_peek(ConditionalStack cstack)
Definition: conditional.c:93
static int64 getPoissonRand(TState *thread, int64 center)
Definition: pgbench.c:795
void PQclear(PGresult *res)
Definition: fe-exec.c:671
int64 sleep_until
Definition: pgbench.c:343
static bool evaluateSleep(CState *st, int argc, char **argv, int *usecs)
Definition: pgbench.c:2635
PGconn * con
Definition: pgbench.c:328
static PGconn * doConnect(void)
Definition: pgbench.c:1096
#define Assert(condition)
Definition: c.h:699
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:1732
#define INSTR_TIME_GET_MICROSEC(t)
Definition: instr_time.h:202
static bool valueTruth(PgBenchValue *pval)
Definition: pgbench.c:1579
bool conditional_stack_poke(ConditionalStack cstack, ifState new_state)
Definition: conditional.c:105
volatile bool timer_exceeded
Definition: pgbench.c:201
Command ** commands
Definition: pgbench.c:454
int64 latency_limit
Definition: pgbench.c:150
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:153
#define INT64_FORMAT
Definition: c.h:367
bool conditional_stack_empty(ConditionalStack cstack)
Definition: conditional.c:117
int64 throttle_delay
Definition: pgbench.c:142
int i
instr_time conn_time
Definition: pgbench.c:400
static bool putVariableValue(CState *st, const char *context, char *name, const PgBenchValue *value)
Definition: pgbench.c:1412
bool prepared[MAX_SCRIPTS]
Definition: pgbench.c:347
static void processXactStats(TState *thread, CState *st, instr_time *now, bool skipped, StatsData *agg)
Definition: pgbench.c:3364
int use_file
Definition: pgbench.c:333
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753
bool is_latencies
Definition: pgbench.c:189

◆ doLog()

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

Definition at line 3283 of file pgbench.c.

References accumStats(), Assert, StatsData::cnt, CState::cnt, gettimeofday(), CState::id, initStats(), INT64_FORMAT, StatsData::lag, StatsData::latency, logfile, TState::logfile, SimpleStats::max, SimpleStats::min, pg_erand48(), TState::random_state, StatsData::skipped, StatsData::start_time, SimpleStats::sum, SimpleStats::sum2, and CState::use_file.

Referenced by processXactStats(), and threadRun().

3285 {
3286  FILE *logfile = thread->logfile;
3287 
3288  Assert(use_log);
3289 
3290  /*
3291  * Skip the log entry if sampling is enabled and this row doesn't belong
3292  * to the random sample.
3293  */
3294  if (sample_rate != 0.0 &&
3295  pg_erand48(thread->random_state) > sample_rate)
3296  return;
3297 
3298  /* should we aggregate the results or not? */
3299  if (agg_interval > 0)
3300  {
3301  /*
3302  * Loop until we reach the interval of the current moment, and print
3303  * any empty intervals in between (this may happen with very low tps,
3304  * e.g. --rate=0.1).
3305  */
3306  time_t now = time(NULL);
3307 
3308  while (agg->start_time + agg_interval <= now)
3309  {
3310  /* print aggregated report to logfile */
3311  fprintf(logfile, "%ld " INT64_FORMAT " %.0f %.0f %.0f %.0f",
3312  (long) agg->start_time,
3313  agg->cnt,
3314  agg->latency.sum,
3315  agg->latency.sum2,
3316  agg->latency.min,
3317  agg->latency.max);
3318  if (throttle_delay)
3319  {
3320  fprintf(logfile, " %.0f %.0f %.0f %.0f",
3321  agg->lag.sum,
3322  agg->lag.sum2,
3323  agg->lag.min,
3324  agg->lag.max);
3325  if (latency_limit)
3326  fprintf(logfile, " " INT64_FORMAT, agg->skipped);
3327  }
3328  fputc('\n', logfile);
3329 
3330  /* reset data and move to next interval */
3331  initStats(agg, agg->start_time + agg_interval);
3332  }
3333 
3334  /* accumulate the current transaction */
3335  accumStats(agg, skipped, latency, lag);
3336  }
3337  else
3338  {
3339  /* no, print raw transactions */
3340  struct timeval tv;
3341 
3342  gettimeofday(&tv, NULL);
3343  if (skipped)
3344  fprintf(logfile, "%d " INT64_FORMAT " skipped %d %ld %ld",
3345  st->id, st->cnt, st->use_file,
3346  (long) tv.tv_sec, (long) tv.tv_usec);
3347  else
3348  fprintf(logfile, "%d " INT64_FORMAT " %.0f %d %ld %ld",
3349  st->id, st->cnt, latency, st->use_file,
3350  (long) tv.tv_sec, (long) tv.tv_usec);
3351  if (throttle_delay)
3352  fprintf(logfile, " %.0f", lag);
3353  fputc('\n', logfile);
3354  }
3355 }
time_t start_time
Definition: pgbench.c:244
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:105
double sample_rate
Definition: pgbench.c:136
int id
Definition: pgbench.c:329
unsigned short random_state[3]
Definition: pgbench.c:392
SimpleStats lag
Definition: pgbench.c:249
static void initStats(StatsData *sd, time_t start_time)
Definition: pgbench.c:1032
double sum
Definition: pgbench.c:234
bool use_log
Definition: pgbench.c:179
static FILE * logfile
Definition: pg_regress.c:100
SimpleStats latency
Definition: pgbench.c:248
FILE * logfile
Definition: pgbench.c:394
int64 cnt
Definition: pgbench.c:245
int64 cnt
Definition: pgbench.c:350
int64 skipped
Definition: pgbench.c:246
double max
Definition: pgbench.c:233
static void accumStats(StatsData *stats, bool skipped, double lat, double lag)
Definition: pgbench.c:1045
double pg_erand48(unsigned short xseed[3])
Definition: erand48.c:79
#define Assert(condition)
Definition: c.h:699
double sum2
Definition: pgbench.c:235
int64 latency_limit
Definition: pgbench.c:150
#define INT64_FORMAT
Definition: c.h:367
int64 throttle_delay
Definition: pgbench.c:142
int use_file
Definition: pgbench.c:333
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
double min
Definition: pgbench.c:232
int agg_interval
Definition: pgbench.c:181

◆ evalFunc()

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

Definition at line 2319 of file pgbench.c.

References evalLazyFunc(), evalStandardFunc(), and isLazyFunc().

Referenced by evaluateExpr().

2321 {
2322  if (isLazyFunc(func))
2323  return evalLazyFunc(thread, st, func, args, retval);
2324  else
2325  return evalStandardFunc(thread, st, func, args, retval);
2326 }
static bool isLazyFunc(PgBenchFunction func)
Definition: pgbench.c:1679
static bool evalLazyFunc(TState *thread, CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:1686
static bool evalStandardFunc(TState *thread, CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:1801

◆ evalLazyFunc()

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

Definition at line 1686 of file pgbench.c.

References a1, a2, Assert, coerceToBool(), evaluateExpr(), PgBenchExprLink::expr, isLazyFunc(), PgBenchExprLink::next, PGBENCH_AND, PGBENCH_CASE, PGBENCH_OR, PGBT_NULL, setBoolValue(), setNullValue(), PgBenchValue::type, and valueTruth().

Referenced by evalFunc().

1688 {
1689  PgBenchValue a1, a2;
1690  bool ba1, ba2;
1691 
1692  Assert(isLazyFunc(func) && args != NULL && args->next != NULL);
1693 
1694  /* args points to first condition */
1695  if (!evaluateExpr(thread, st, args->expr, &a1))
1696  return false;
1697 
1698  /* second condition for AND/OR and corresponding branch for CASE */
1699  args = args->next;
1700 
1701  switch (func)
1702  {
1703  case PGBENCH_AND:
1704  if (a1.type == PGBT_NULL)
1705  {
1706  setNullValue(retval);
1707  return true;
1708  }
1709 
1710  if (!coerceToBool(&a1, &ba1))
1711  return false;
1712 
1713  if (!ba1)
1714  {
1715  setBoolValue(retval, false);
1716  return true;
1717  }
1718 
1719  if (!evaluateExpr(thread, st, args->expr, &a2))
1720  return false;
1721 
1722  if (a2.type == PGBT_NULL)
1723  {
1724  setNullValue(retval);
1725  return true;
1726  }
1727  else if (!coerceToBool(&a2, &ba2))
1728  return false;
1729  else
1730  {
1731  setBoolValue(retval, ba2);
1732  return true;
1733  }
1734 
1735  return true;
1736 
1737  case PGBENCH_OR:
1738 
1739  if (a1.type == PGBT_NULL)
1740  {
1741  setNullValue(retval);
1742  return true;
1743  }
1744 
1745  if (!coerceToBool(&a1, &ba1))
1746  return false;
1747 
1748  if (ba1)
1749  {
1750  setBoolValue(retval, true);
1751  return true;
1752  }
1753 
1754  if (!evaluateExpr(thread, st, args->expr, &a2))
1755  return false;
1756 
1757  if (a2.type == PGBT_NULL)
1758  {
1759  setNullValue(retval);
1760  return true;
1761  }
1762  else if (!coerceToBool(&a2, &ba2))
1763  return false;
1764  else
1765  {
1766  setBoolValue(retval, ba2);
1767  return true;
1768  }
1769 
1770  case PGBENCH_CASE:
1771  /* when true, execute branch */
1772  if (valueTruth(&a1))
1773  return evaluateExpr(thread, st, args->expr, retval);
1774 
1775  /* now args contains next condition or final else expression */
1776  args = args->next;
1777 
1778  /* final else case? */
1779  if (args->next == NULL)
1780  return evaluateExpr(thread, st, args->expr, retval);
1781 
1782  /* no, another when, proceed */
1783  return evalLazyFunc(thread, st, PGBENCH_CASE, args, retval);
1784 
1785  default:
1786  /* internal error, cannot get here */
1787  Assert(0);
1788  break;
1789  }
1790  return false;
1791 }
static bool coerceToBool(PgBenchValue *pval, bool *bval)
Definition: pgbench.c:1559
static bool evaluateExpr(TState *, CState *, PgBenchExpr *, PgBenchValue *)
Definition: pgbench.c:2335
static void setBoolValue(PgBenchValue *pv, bool bval)
Definition: pgbench.c:1657
static void setNullValue(PgBenchValue *pv)
Definition: pgbench.c:1649
static bool isLazyFunc(PgBenchFunction func)
Definition: pgbench.c:1679
static bool evalLazyFunc(TState *thread, CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:1686
static FormData_pg_attribute a1
Definition: heap.c:147
#define Assert(condition)
Definition: c.h:699
static bool valueTruth(PgBenchValue *pval)
Definition: pgbench.c:1579
PgBenchValueType type
Definition: pgbench.h:46
static FormData_pg_attribute a2
Definition: heap.c:153

◆ evalStandardFunc()

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

Definition at line 1801 of file pgbench.c.

References generate_unaccent_rules::args, Assert, PgBenchValue::bval, coerceToBool(), coerceToDouble(), coerceToInt(), CState::command, PgBenchValue::dval, evaluateExpr(), getExponentialRand(), getGaussianRand(), getHashFnv1a(), getHashMurmur2(), getrand(), getZipfianRand(), i, INT64_FORMAT, PgBenchValue::ival, M_PI, Max, MAX_FARGS, MAX_ZIPFIAN_PARAM, Min, MIN_GAUSSIAN_PARAM, PgBenchExprLink::next, PG_INT64_MIN, 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_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, setBoolValue(), setDoubleValue(), setIntValue(), setNullValue(), PgBenchValue::type, generate_unaccent_rules::type, PgBenchValue::u, CState::use_file, and val.

Referenced by evalFunc().

1804 {
1805  /* evaluate all function arguments */
1806  int nargs = 0;
1807  PgBenchValue vargs[MAX_FARGS];
1808  PgBenchExprLink *l = args;
1809  bool has_null = false;
1810 
1811  for (nargs = 0; nargs < MAX_FARGS && l != NULL; nargs++, l = l->next)
1812  {
1813  if (!evaluateExpr(thread, st, l->expr, &vargs[nargs]))
1814  return false;
1815  has_null |= vargs[nargs].type == PGBT_NULL;
1816  }
1817 
1818  if (l != NULL)
1819  {
1820  fprintf(stderr,
1821  "too many function arguments, maximum is %d\n", MAX_FARGS);
1822  return false;
1823  }
1824 
1825  /* NULL arguments */
1826  if (has_null && func != PGBENCH_IS && func != PGBENCH_DEBUG)
1827  {
1828  setNullValue(retval);
1829  return true;
1830  }
1831 
1832  /* then evaluate function */
1833  switch (func)
1834  {
1835  /* overloaded operators */
1836  case PGBENCH_ADD:
1837  case PGBENCH_SUB:
1838  case PGBENCH_MUL:
1839  case PGBENCH_DIV:
1840  case PGBENCH_MOD:
1841  case PGBENCH_EQ:
1842  case PGBENCH_NE:
1843  case PGBENCH_LE:
1844  case PGBENCH_LT:
1845  {
1846  PgBenchValue *lval = &vargs[0],
1847  *rval = &vargs[1];
1848 
1849  Assert(nargs == 2);
1850 
1851  /* overloaded type management, double if some double */
1852  if ((lval->type == PGBT_DOUBLE ||
1853  rval->type == PGBT_DOUBLE) && func != PGBENCH_MOD)
1854  {
1855  double ld,
1856  rd;
1857 
1858  if (!coerceToDouble(lval, &ld) ||
1859  !coerceToDouble(rval, &rd))
1860  return false;
1861 
1862  switch (func)
1863  {
1864  case PGBENCH_ADD:
1865  setDoubleValue(retval, ld + rd);
1866  return true;
1867 
1868  case PGBENCH_SUB:
1869  setDoubleValue(retval, ld - rd);
1870  return true;
1871 
1872  case PGBENCH_MUL:
1873  setDoubleValue(retval, ld * rd);
1874  return true;
1875 
1876  case PGBENCH_DIV:
1877  setDoubleValue(retval, ld / rd);
1878  return true;
1879 
1880  case PGBENCH_EQ:
1881  setBoolValue(retval, ld == rd);
1882  return true;
1883 
1884  case PGBENCH_NE:
1885  setBoolValue(retval, ld != rd);
1886  return true;
1887 
1888  case PGBENCH_LE:
1889  setBoolValue(retval, ld <= rd);
1890  return true;
1891 
1892  case PGBENCH_LT:
1893  setBoolValue(retval, ld < rd);
1894  return true;
1895 
1896  default:
1897  /* cannot get here */
1898  Assert(0);
1899  }
1900  }
1901  else /* we have integer operands, or % */
1902  {
1903  int64 li,
1904  ri;
1905 
1906  if (!coerceToInt(lval, &li) ||
1907  !coerceToInt(rval, &ri))
1908  return false;
1909 
1910  switch (func)
1911  {
1912  case PGBENCH_ADD:
1913  setIntValue(retval, li + ri);
1914  return true;
1915 
1916  case PGBENCH_SUB:
1917  setIntValue(retval, li - ri);
1918  return true;
1919 
1920  case PGBENCH_MUL:
1921  setIntValue(retval, li * ri);
1922  return true;
1923 
1924  case PGBENCH_EQ:
1925  setBoolValue(retval, li == ri);
1926  return true;
1927 
1928  case PGBENCH_NE:
1929  setBoolValue(retval, li != ri);
1930  return true;
1931 
1932  case PGBENCH_LE:
1933  setBoolValue(retval, li <= ri);
1934  return true;
1935 
1936  case PGBENCH_LT:
1937  setBoolValue(retval, li < ri);
1938  return true;
1939 
1940  case PGBENCH_DIV:
1941  case PGBENCH_MOD:
1942  if (ri == 0)
1943  {
1944  fprintf(stderr, "division by zero\n");
1945  return false;
1946  }
1947  /* special handling of -1 divisor */
1948  if (ri == -1)
1949  {
1950  if (func == PGBENCH_DIV)
1951  {
1952  /* overflow check (needed for INT64_MIN) */
1953  if (li == PG_INT64_MIN)
1954  {
1955  fprintf(stderr, "bigint out of range\n");
1956  return false;
1957  }
1958  else
1959  setIntValue(retval, -li);
1960  }
1961  else
1962  setIntValue(retval, 0);
1963  return true;
1964  }
1965  /* else divisor is not -1 */
1966  if (func == PGBENCH_DIV)
1967  setIntValue(retval, li / ri);
1968  else /* func == PGBENCH_MOD */
1969  setIntValue(retval, li % ri);
1970 
1971  return true;
1972 
1973  default:
1974  /* cannot get here */
1975  Assert(0);
1976  }
1977  }
1978  }
1979 
1980  /* integer bitwise operators */
1981  case PGBENCH_BITAND:
1982  case PGBENCH_BITOR:
1983  case PGBENCH_BITXOR:
1984  case PGBENCH_LSHIFT:
1985  case PGBENCH_RSHIFT:
1986  {
1987  int64 li, ri;
1988 
1989  if (!coerceToInt(&vargs[0], &li) || !coerceToInt(&vargs[1], &ri))
1990  return false;
1991 
1992  if (func == PGBENCH_BITAND)
1993  setIntValue(retval, li & ri);
1994  else if (func == PGBENCH_BITOR)
1995  setIntValue(retval, li | ri);
1996  else if (func == PGBENCH_BITXOR)
1997  setIntValue(retval, li ^ ri);
1998  else if (func == PGBENCH_LSHIFT)
1999  setIntValue(retval, li << ri);
2000  else if (func == PGBENCH_RSHIFT)
2001  setIntValue(retval, li >> ri);
2002  else /* cannot get here */
2003  Assert(0);
2004 
2005  return true;
2006  }
2007 
2008  /* logical operators */
2009  case PGBENCH_NOT:
2010  {
2011  bool b;
2012  if (!coerceToBool(&vargs[0], &b))
2013  return false;
2014 
2015  setBoolValue(retval, !b);
2016  return true;
2017  }
2018 
2019  /* no arguments */
2020  case PGBENCH_PI:
2021  setDoubleValue(retval, M_PI);
2022  return true;
2023 
2024  /* 1 overloaded argument */
2025  case PGBENCH_ABS:
2026  {
2027  PgBenchValue *varg = &vargs[0];
2028 
2029  Assert(nargs == 1);
2030 
2031  if (varg->type == PGBT_INT)
2032  {
2033  int64 i = varg->u.ival;
2034 
2035  setIntValue(retval, i < 0 ? -i : i);
2036  }
2037  else
2038  {
2039  double d = varg->u.dval;
2040 
2041  Assert(varg->type == PGBT_DOUBLE);
2042  setDoubleValue(retval, d < 0.0 ? -d : d);
2043  }
2044 
2045  return true;
2046  }
2047 
2048  case PGBENCH_DEBUG:
2049  {
2050  PgBenchValue *varg = &vargs[0];
2051 
2052  Assert(nargs == 1);
2053 
2054  fprintf(stderr, "debug(script=%d,command=%d): ",
2055  st->use_file, st->command + 1);
2056 
2057  if (varg->type == PGBT_NULL)
2058  fprintf(stderr, "null\n");
2059  else if (varg->type == PGBT_BOOLEAN)
2060  fprintf(stderr, "boolean %s\n", varg->u.bval ? "true" : "false");
2061  else if (varg->type == PGBT_INT)
2062  fprintf(stderr, "int " INT64_FORMAT "\n", varg->u.ival);
2063  else if (varg->type == PGBT_DOUBLE)
2064  fprintf(stderr, "double %.*g\n", DBL_DIG, varg->u.dval);
2065  else /* internal error, unexpected type */
2066  Assert(0);
2067 
2068  *retval = *varg;
2069 
2070  return true;
2071  }
2072 
2073  /* 1 double argument */
2074  case PGBENCH_DOUBLE:
2075  case PGBENCH_SQRT:
2076  case PGBENCH_LN:
2077  case PGBENCH_EXP:
2078  {
2079  double dval;
2080 
2081  Assert(nargs == 1);
2082 
2083  if (!coerceToDouble(&vargs[0], &dval))
2084  return false;
2085 
2086  if (func == PGBENCH_SQRT)
2087  dval = sqrt(dval);
2088  else if (func == PGBENCH_LN)
2089  dval = log(dval);
2090  else if (func == PGBENCH_EXP)
2091  dval = exp(dval);
2092  /* else is cast: do nothing */
2093 
2094  setDoubleValue(retval, dval);
2095  return true;
2096  }
2097 
2098  /* 1 int argument */
2099  case PGBENCH_INT:
2100  {
2101  int64 ival;
2102 
2103  Assert(nargs == 1);
2104 
2105  if (!coerceToInt(&vargs[0], &ival))
2106  return false;
2107 
2108  setIntValue(retval, ival);
2109  return true;
2110  }
2111 
2112  /* variable number of arguments */
2113  case PGBENCH_LEAST:
2114  case PGBENCH_GREATEST:
2115  {
2116  bool havedouble;
2117  int i;
2118 
2119  Assert(nargs >= 1);
2120 
2121  /* need double result if any input is double */
2122  havedouble = false;
2123  for (i = 0; i < nargs; i++)
2124  {
2125  if (vargs[i].type == PGBT_DOUBLE)
2126  {
2127  havedouble = true;
2128  break;
2129  }
2130  }
2131  if (havedouble)
2132  {
2133  double extremum;
2134 
2135  if (!coerceToDouble(&vargs[0], &extremum))
2136  return false;
2137  for (i = 1; i < nargs; i++)
2138  {
2139  double dval;
2140 
2141  if (!coerceToDouble(&vargs[i], &dval))
2142  return false;
2143  if (func == PGBENCH_LEAST)
2144  extremum = Min(extremum, dval);
2145  else
2146  extremum = Max(extremum, dval);
2147  }
2148  setDoubleValue(retval, extremum);
2149  }
2150  else
2151  {
2152  int64 extremum;
2153 
2154  if (!coerceToInt(&vargs[0], &extremum))
2155  return false;
2156  for (i = 1; i < nargs; i++)
2157  {
2158  int64 ival;
2159 
2160  if (!coerceToInt(&vargs[i], &ival))
2161  return false;
2162  if (func == PGBENCH_LEAST)
2163  extremum = Min(extremum, ival);
2164  else
2165  extremum = Max(extremum, ival);
2166  }
2167  setIntValue(retval, extremum);
2168  }
2169  return true;
2170  }
2171 
2172  /* random functions */
2173  case PGBENCH_RANDOM:
2177  {
2178  int64 imin,
2179  imax;
2180 
2181  Assert(nargs >= 2);
2182 
2183  if (!coerceToInt(&vargs[0], &imin) ||
2184  !coerceToInt(&vargs[1], &imax))
2185  return false;
2186 
2187  /* check random range */
2188  if (imin > imax)
2189  {
2190  fprintf(stderr, "empty range given to random\n");
2191  return false;
2192  }
2193  else if (imax - imin < 0 || (imax - imin) + 1 < 0)
2194  {
2195  /* prevent int overflows in random functions */
2196  fprintf(stderr, "random range is too large\n");
2197  return false;
2198  }
2199 
2200  if (func == PGBENCH_RANDOM)
2201  {
2202  Assert(nargs == 2);
2203  setIntValue(retval, getrand(thread, imin, imax));
2204  }
2205  else /* gaussian & exponential */
2206  {
2207  double param;
2208 
2209  Assert(nargs == 3);
2210 
2211  if (!coerceToDouble(&vargs[2], &param))
2212  return false;
2213 
2214  if (func == PGBENCH_RANDOM_GAUSSIAN)
2215  {
2216  if (param < MIN_GAUSSIAN_PARAM)
2217  {
2218  fprintf(stderr,
2219  "gaussian parameter must be at least %f "
2220  "(not %f)\n", MIN_GAUSSIAN_PARAM, param);
2221  return false;
2222  }
2223 
2224  setIntValue(retval,
2225  getGaussianRand(thread, imin, imax, param));
2226  }
2227  else if (func == PGBENCH_RANDOM_ZIPFIAN)
2228  {
2229  if (param <= 0.0 || param == 1.0 || param > MAX_ZIPFIAN_PARAM)
2230  {
2231  fprintf(stderr,
2232  "zipfian parameter must be in range (0, 1) U (1, %d]"
2233  " (got %f)\n", MAX_ZIPFIAN_PARAM, param);
2234  return false;
2235  }
2236  setIntValue(retval,
2237  getZipfianRand(thread, imin, imax, param));
2238  }
2239  else /* exponential */
2240  {
2241  if (param <= 0.0)
2242  {
2243  fprintf(stderr,
2244  "exponential parameter must be greater than zero"
2245  " (got %f)\n", param);
2246  return false;
2247  }
2248 
2249  setIntValue(retval,
2250  getExponentialRand(thread, imin, imax, param));
2251  }
2252  }
2253 
2254  return true;
2255  }
2256 
2257  case PGBENCH_POW:
2258  {
2259  PgBenchValue *lval = &vargs[0];
2260  PgBenchValue *rval = &vargs[1];
2261  double ld,
2262  rd;
2263 
2264  Assert(nargs == 2);
2265 
2266  if (!coerceToDouble(lval, &ld) ||
2267  !coerceToDouble(rval, &rd))
2268  return false;
2269 
2270  setDoubleValue(retval, pow(ld, rd));
2271 
2272  return true;
2273  }
2274 
2275  case PGBENCH_IS:
2276  {
2277  Assert(nargs == 2);
2278  /* note: this simple implementation is more permissive than SQL */
2279  setBoolValue(retval,
2280  vargs[0].type == vargs[1].type &&
2281  vargs[0].u.bval == vargs[1].u.bval);
2282  return true;
2283  }
2284 
2285  /* hashing */
2286  case PGBENCH_HASH_FNV1A:
2287  case PGBENCH_HASH_MURMUR2:
2288  {
2289  int64 val,
2290  seed;
2291 
2292  Assert(nargs == 2);
2293 
2294  if (!coerceToInt(&vargs[0], &val) ||
2295  !coerceToInt(&vargs[1], &seed))
2296  return false;
2297 
2298  if (func == PGBENCH_HASH_MURMUR2)
2299  setIntValue(retval, getHashMurmur2(val, seed));
2300  else if (func == PGBENCH_HASH_FNV1A)
2301  setIntValue(retval, getHashFnv1a(val, seed));
2302  else
2303  /* cannot get here */
2304  Assert(0);
2305 
2306  return true;
2307  }
2308 
2309  default:
2310  /* cannot get here */
2311  Assert(0);
2312  /* dead code to avoid a compiler warning */
2313  return false;
2314  }
2315 }
static bool coerceToBool(PgBenchValue *pval, bool *bval)
Definition: pgbench.c:1559
static bool evaluateExpr(TState *, CState *, PgBenchExpr *, PgBenchValue *)
Definition: pgbench.c:2335
static int64 getrand(TState *thread, int64 min, int64 max)
Definition: pgbench.c:696
static int64 getHashMurmur2(int64 val, uint64 seed)
Definition: pgbench.c:969
static int64 getHashFnv1a(int64 val, uint64 seed)
Definition: pgbench.c:944
#define Min(x, y)
Definition: c.h:857
union PgBenchValue::@39 u
static bool coerceToDouble(PgBenchValue *pval, double *dval)
Definition: pgbench.c:1628
static void setDoubleValue(PgBenchValue *pv, double dval)
Definition: pgbench.c:1673
#define MIN_GAUSSIAN_PARAM
Definition: pgbench.c:109
static int64 getGaussianRand(TState *thread, int64 min, int64 max, double parameter)
Definition: pgbench.c:739
#define MAX_FARGS
Definition: pgbench.c:1794
static void setBoolValue(PgBenchValue *pv, bool bval)
Definition: pgbench.c:1657
#define M_PI
Definition: pgbench.c:57
static void setNullValue(PgBenchValue *pv)
Definition: pgbench.c:1649
#define PG_INT64_MIN
Definition: c.h:410
#define MAX_ZIPFIAN_PARAM
Definition: pgbench.c:110
static int64 getZipfianRand(TState *thread, int64 min, int64 max, double s)
Definition: pgbench.c:927
int command
Definition: pgbench.c:334
double dval
Definition: pgbench.h:50
#define Max(x, y)
Definition: c.h:851
#define Assert(condition)
Definition: c.h:699
static void setIntValue(PgBenchValue *pv, int64 ival)
Definition: pgbench.c:1665
#define INT64_FORMAT
Definition: c.h:367
bool bval
Definition: pgbench.h:51
PgBenchValueType type
Definition: pgbench.h:46
static int64 getExponentialRand(TState *thread, int64 min, int64 max, double parameter)
Definition: pgbench.c:716
int i
static bool coerceToInt(PgBenchValue *pval, int64 *ival)
Definition: pgbench.c:1600
int64 ival
Definition: pgbench.h:49
int use_file
Definition: pgbench.c:333
long val
Definition: informix.c:689

◆ evaluateExpr()

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

Definition at line 2335 of file pgbench.c.

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

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

2336 {
2337  switch (expr->etype)
2338  {
2339  case ENODE_CONSTANT:
2340  {
2341  *retval = expr->u.constant;
2342  return true;
2343  }
2344 
2345  case ENODE_VARIABLE:
2346  {
2347  Variable *var;
2348 
2349  if ((var = lookupVariable(st, expr->u.variable.varname)) == NULL)
2350  {
2351  fprintf(stderr, "undefined variable \"%s\"\n",
2352  expr->u.variable.varname);
2353  return false;
2354  }
2355 
2356  if (!makeVariableValue(var))
2357  return false;
2358 
2359  *retval = var->value;
2360  return true;
2361  }
2362 
2363  case ENODE_FUNCTION:
2364  return evalFunc(thread, st,
2365  expr->u.function.function,
2366  expr->u.function.args,
2367  retval);
2368 
2369  default:
2370  /* internal error which should never occur */
2371  fprintf(stderr, "unexpected enode type in evaluation: %d\n",
2372  expr->etype);
2373  exit(1);
2374  }
2375 }
PgBenchValue constant
Definition: pgbench.h:114
static Variable * lookupVariable(CState *st, char *name)
Definition: pgbench.c:1187
struct PgBenchExpr::@40::@41 variable
static bool evalFunc(TState *thread, CState *st, PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
Definition: pgbench.c:2319
static bool makeVariableValue(Variable *var)
Definition: pgbench.c:1247
PgBenchValue value
Definition: pgbench.c:217
PgBenchFunction function
Definition: pgbench.h:121
union PgBenchExpr::@40 u
PgBenchExprType etype
Definition: pgbench.h:111

◆ evaluateSleep()

static bool evaluateSleep ( CState st,
int  argc,
char **  argv,
int *  usecs 
)
static

Definition at line 2635 of file pgbench.c.

References getVariable(), and pg_strcasecmp().

Referenced by doCustom().

2636 {
2637  char *var;
2638  int usec;
2639 
2640  if (*argv[1] == ':')
2641  {
2642  if ((var = getVariable(st, argv[1] + 1)) == NULL)
2643  {
2644  fprintf(stderr, "%s: undefined variable \"%s\"\n",
2645  argv[0], argv[1]);
2646  return false;
2647  }
2648  usec = atoi(var);
2649  }
2650  else
2651  usec = atoi(argv[1]);
2652 
2653  if (argc > 2)
2654  {
2655  if (pg_strcasecmp(argv[2], "ms") == 0)
2656  usec *= 1000;
2657  else if (pg_strcasecmp(argv[2], "s") == 0)
2658  usec *= 1000000;
2659  }
2660  else
2661  usec *= 1000000;
2662 
2663  *usecs = usec;
2664  return true;
2665 }
static char * getVariable(CState *st, char *name)
Definition: pgbench.c:1214
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

◆ executeStatement()

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

Definition at line 1066 of file pgbench.c.

References PGRES_COMMAND_OK, PQclear(), PQerrorMessage(), PQexec(), and PQresultStatus().

Referenced by initCreateFKeys(), initCreatePKeys(), initCreateTables(), initDropTables(), initGenerateData(), and initVacuum().

1067 {
1068  PGresult *res;
1069 
1070  res = PQexec(con, sql);
1071  if (PQresultStatus(res) != PGRES_COMMAND_OK)
1072  {
1073  fprintf(stderr, "%s", PQerrorMessage(con));
1074  exit(1);
1075  }
1076  PQclear(res);
1077 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6116
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
void PQclear(PGresult *res)
Definition: fe-exec.c:671
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1897

◆ findBuiltin()

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

Definition at line 4416 of file pgbench.c.

References i, lengthof, and listAvailableScripts().

Referenced by main().

4417 {
4418  int i,
4419  found = 0,
4420  len = strlen(name);
4421  const BuiltinScript *result = NULL;
4422 
4423  for (i = 0; i < lengthof(builtin_script); i++)
4424  {
4425  if (strncmp(builtin_script[i].name, name, len) == 0)
4426  {
4427  result = &builtin_script[i];
4428  found++;
4429  }
4430  }
4431 
4432  /* ok, unambiguous result */
4433  if (found == 1)
4434  return result;
4435 
4436  /* error cases */
4437  if (found == 0)
4438  fprintf(stderr, "no builtin script found for name \"%s\"\n", name);
4439  else /* found > 1 */
4440  fprintf(stderr,
4441  "ambiguous builtin name: %d builtin scripts found for prefix \"%s\"\n", found, name);
4442 
4444  exit(1);
4445 }
static void listAvailableScripts(void)
Definition: pgbench.c:4404
#define lengthof(array)
Definition: c.h:629
static const BuiltinScript builtin_script[]
Definition: pgbench.c:473
const char * name
Definition: encode.c:521
int i

◆ finishCon()

static void finishCon ( CState st)
static

Definition at line 5940 of file pgbench.c.

References CState::con, and PQfinish().

Referenced by disconnect_all(), doCustom(), and threadRun().

5941 {
5942  if (st->con != NULL)
5943  {
5944  PQfinish(st->con);
5945  st->con = NULL;
5946  }
5947 }
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3638
PGconn * con
Definition: pgbench.c:328

◆ generalizedHarmonicNumber()

static double generalizedHarmonicNumber ( int64  n,
double  s 
)
static

Definition at line 811 of file pgbench.c.

References i.

Referenced by zipfSetCacheCell().

812 {
813  int i;
814  double ans = 0.0;
815 
816  for (i = n; i > 1; i--)
817  ans += pow(i, -s);
818  return ans + 1.0;
819 }
int i

◆ getExponentialRand()

static int64 getExponentialRand ( TState thread,
int64  min,
int64  max,
double  parameter 
)
static

Definition at line 716 of file pgbench.c.

References Assert, pg_erand48(), and TState::random_state.

Referenced by evalStandardFunc().

717 {
718  double cut,
719  uniform,
720  rand;
721 
722  /* abort if wrong parameter, but must really be checked beforehand */
723  Assert(parameter > 0.0);
724  cut = exp(-parameter);
725  /* erand in [0, 1), uniform in (0, 1] */
726  uniform = 1.0 - pg_erand48(thread->random_state);
727 
728  /*
729  * inner expression in (cut, 1] (if parameter > 0), rand in [0, 1)
730  */
731  Assert((1.0 - cut) != 0.0);
732  rand = -log(cut + (1.0 - cut) * uniform) / parameter;
733  /* return int64 random number within between min and max */
734  return min + (int64) ((max - min + 1) * rand);
735 }
unsigned short random_state[3]
Definition: pgbench.c:392
double pg_erand48(unsigned short xseed[3])
Definition: erand48.c:79
#define Assert(condition)
Definition: c.h:699

◆ getGaussianRand()

static int64 getGaussianRand ( TState thread,
int64  min,
int64  max,
double  parameter 
)
static

Definition at line 739 of file pgbench.c.

References Assert, M_PI, MIN_GAUSSIAN_PARAM, pg_erand48(), and TState::random_state.

Referenced by evalStandardFunc().

740 {
741  double stdev;
742  double rand;
743 
744  /* abort if parameter is too low, but must really be checked beforehand */
745  Assert(parameter >= MIN_GAUSSIAN_PARAM);
746 
747  /*
748  * Get user specified random number from this loop, with -parameter <
749  * stdev <= parameter
750  *
751  * This loop is executed until the number is in the expected range.
752  *
753  * As the minimum parameter is 2.0, the probability of looping is low:
754  * sqrt(-2 ln(r)) <= 2 => r >= e^{-2} ~ 0.135, then when taking the
755  * average sinus multiplier as 2/pi, we have a 8.6% looping probability in
756  * the worst case. For a parameter value of 5.0, the looping probability
757  * is about e^{-5} * 2 / pi ~ 0.43%.
758  */
759  do
760  {
761  /*
762  * pg_erand48 generates [0,1), but for the basic version of the
763  * Box-Muller transform the two uniformly distributed random numbers
764  * are expected in (0, 1] (see
765  * http://en.wikipedia.org/wiki/Box_muller)
766  */
767  double rand1 = 1.0 - pg_erand48(thread->random_state);
768  double rand2 = 1.0 - pg_erand48(thread->random_state);
769 
770  /* Box-Muller basic form transform */
771  double var_sqrt = sqrt(-2.0 * log(rand1));
772 
773  stdev = var_sqrt * sin(2.0 * M_PI * rand2);
774 
775  /*
776  * we may try with cos, but there may be a bias induced if the
777  * previous value fails the test. To be on the safe side, let us try
778  * over.
779  */
780  }
781  while (stdev < -parameter || stdev >= parameter);
782 
783  /* stdev is in [-parameter, parameter), normalization to [0,1) */
784  rand = (stdev + parameter) / (parameter * 2.0);
785 
786  /* return int64 random number within between min and max */
787  return min + (int64) ((max - min + 1) * rand);
788 }
unsigned short random_state[3]
Definition: pgbench.c:392
#define MIN_GAUSSIAN_PARAM
Definition: pgbench.c:109
#define M_PI
Definition: pgbench.c:57
double pg_erand48(unsigned short xseed[3])
Definition: erand48.c:79
#define Assert(condition)
Definition: c.h:699

◆ getHashFnv1a()

static int64 getHashFnv1a ( int64  val,
uint64  seed 
)
static

Definition at line 944 of file pgbench.c.

References FNV_OFFSET_BASIS, FNV_PRIME, and i.

Referenced by evalStandardFunc().

945 {
946  int64 result;
947  int i;
948 
949  result = FNV_OFFSET_BASIS ^ seed;
950  for (i = 0; i < 8; ++i)
951  {
952  int32 octet = val & 0xff;
953 
954  val = val >> 8;
955  result = result ^ octet;
956  result = result * FNV_PRIME;
957  }
958 
959  return result;
960 }
#define FNV_PRIME
Definition: pgbench.c:67
#define FNV_OFFSET_BASIS
Definition: pgbench.c:68
signed int int32
Definition: c.h:313
int i
long val
Definition: informix.c:689

◆ getHashMurmur2()

static int64 getHashMurmur2 ( int64  val,
uint64  seed 
)
static

Definition at line 969 of file pgbench.c.

References MM2_MUL, and MM2_ROT.

Referenced by evalStandardFunc().

970 {
971  uint64 result = seed ^ (sizeof(int64) * MM2_MUL);
972  uint64 k = (uint64) val;
973 
974  k *= MM2_MUL;
975  k ^= k >> MM2_ROT;
976  k *= MM2_MUL;
977 
978  result ^= k;
979  result *= MM2_MUL;
980 
981  result ^= result >> MM2_ROT;
982  result *= MM2_MUL;
983  result ^= result >> MM2_ROT;
984 
985  return (int64) result;
986 }
#define MM2_ROT
Definition: pgbench.c:70
long val
Definition: informix.c:689
#define MM2_MUL
Definition: pgbench.c:69

◆ getMetaCommand()

static MetaCommand getMetaCommand ( const char *  cmd)
static

Definition at line 2381 of file pgbench.c.

References META_ELIF, META_ELSE, META_ENDIF, META_IF, META_NONE, META_SET, META_SETSHELL, META_SHELL, META_SLEEP, and pg_strcasecmp().

Referenced by process_backslash_command().

2382 {
2383  MetaCommand mc;
2384 
2385  if (cmd == NULL)
2386  mc = META_NONE;
2387  else if (pg_strcasecmp(cmd, "set") == 0)
2388  mc = META_SET;
2389  else if (pg_strcasecmp(cmd, "setshell") == 0)
2390  mc = META_SETSHELL;
2391  else if (pg_strcasecmp(cmd, "shell") == 0)
2392  mc = META_SHELL;
2393  else if (pg_strcasecmp(cmd, "sleep") == 0)
2394  mc = META_SLEEP;
2395  else if (pg_strcasecmp(cmd, "if") == 0)
2396  mc = META_IF;
2397  else if (pg_strcasecmp(cmd, "elif") == 0)
2398  mc = META_ELIF;
2399  else if (pg_strcasecmp(cmd, "else") == 0)
2400  mc = META_ELSE;
2401  else if (pg_strcasecmp(cmd, "endif") == 0)
2402  mc = META_ENDIF;
2403  else
2404  mc = META_NONE;
2405  return mc;
2406 }
MetaCommand
Definition: pgbench.c:414
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

◆ getPoissonRand()

static int64 getPoissonRand ( TState thread,
int64  center 
)
static

Definition at line 795 of file pgbench.c.

References pg_erand48(), and TState::random_state.

Referenced by doCustom().

796 {
797  /*
798  * Use inverse transform sampling to generate a value > 0, such that the
799  * expected (i.e. average) value is the given argument.
800  */
801  double uniform;
802 
803  /* erand in [0, 1), uniform in (0, 1] */
804  uniform = 1.0 - pg_erand48(thread->random_state);
805 
806  return (int64) (-log(uniform) * ((double) center) + 0.5);
807 }
unsigned short random_state[3]
Definition: pgbench.c:392
double pg_erand48(unsigned short xseed[3])
Definition: erand48.c:79

◆ getQueryParams()

static void getQueryParams ( CState st,
const Command command,
const char **  params 
)
static

Definition at line 1528 of file pgbench.c.

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

Referenced by sendCommand().

1529 {
1530  int i;
1531 
1532  for (i = 0; i < command->argc - 1; i++)
1533  params[i] = getVariable(st, command->argv[i + 1]);
1534 }
static char * getVariable(CState *st, char *name)
Definition: pgbench.c:1214
char * argv[MAX_ARGS]
Definition: pgbench.c:445
int argc
Definition: pgbench.c:444
int i

◆ getrand()

static int64 getrand ( TState thread,
int64  min,
int64  max 
)
static

Definition at line 696 of file pgbench.c.

References pg_erand48(), and TState::random_state.

Referenced by chooseScript(), and evalStandardFunc().

697 {
698  /*
699  * Odd coding is so that min and max have approximately the same chance of
700  * being selected as do numbers between them.
701  *
702  * pg_erand48() is thread-safe and concurrent, which is why we use it
703  * rather than random(), which in glibc is non-reentrant, and therefore
704  * protected by a mutex, and therefore a bottleneck on machines with many
705  * CPUs.
706  */
707  return min + (int64) ((max - min + 1) * pg_erand48(thread->random_state));
708 }
unsigned short random_state[3]
Definition: pgbench.c:392
double pg_erand48(unsigned short xseed[3])
Definition: erand48.c:79

◆ getVariable()

static char* getVariable ( CState st,
char *  name 
)
static

Definition at line 1214 of file pgbench.c.

References Assert, PgBenchValue::bval, PgBenchValue::dval, INT64_FORMAT, PgBenchValue::ival, lookupVariable(), 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().

1215 {
1216  Variable *var;
1217  char stringform[64];
1218 
1219  var = lookupVariable(st, name);
1220  if (var == NULL)
1221  return NULL; /* not found */
1222 
1223  if (var->svalue)
1224  return var->svalue; /* we have it in string form */
1225 
1226  /* We need to produce a string equivalent of the value */
1227  Assert(var->value.type != PGBT_NO_VALUE);
1228  if (var->value.type == PGBT_NULL)
1229  snprintf(stringform, sizeof(stringform), "NULL");
1230  else if (var->value.type == PGBT_BOOLEAN)
1231  snprintf(stringform, sizeof(stringform),
1232  "%s", var->value.u.bval ? "true" : "false");
1233  else if (var->value.type == PGBT_INT)
1234  snprintf(stringform, sizeof(stringform),
1235  INT64_FORMAT, var->value.u.ival);
1236  else if (var->value.type == PGBT_DOUBLE)
1237  snprintf(stringform, sizeof(stringform),
1238  "%.*g", DBL_DIG, var->value.u.dval);
1239  else /* internal error, unexpected type */
1240  Assert(0);
1241  var->svalue = pg_strdup(stringform);
1242  return var->svalue;
1243 }
static Variable * lookupVariable(CState *st, char *name)
Definition: pgbench.c:1187
union PgBenchValue::@39 u
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
char * svalue
Definition: pgbench.c:216
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
PgBenchValue value
Definition: pgbench.c:217
double dval
Definition: pgbench.h:50
#define Assert(condition)
Definition: c.h:699
#define INT64_FORMAT
Definition: c.h:367
const char * name
Definition: encode.c:521
bool bval
Definition: pgbench.h:51
PgBenchValueType type
Definition: pgbench.h:46
int64 ival
Definition: pgbench.h:49

◆ getZipfianRand()

static int64 getZipfianRand ( TState thread,
int64  min,
int64  max,
double  s 
)
static

Definition at line 927 of file pgbench.c.

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

Referenced by evalStandardFunc().

928 {
929  int64 n = max - min + 1;
930 
931  /* abort if parameter is invalid */
932  Assert(s > 0.0 && s != 1.0 && s <= MAX_ZIPFIAN_PARAM);
933 
934 
935  return min - 1 + ((s > 1)
936  ? computeIterativeZipfian(thread, n, s)
937  : computeHarmonicZipfian(thread, n, s));
938 }
#define MAX_ZIPFIAN_PARAM
Definition: pgbench.c:110
static int64 computeHarmonicZipfian(TState *thread, int64 n, double s)
Definition: pgbench.c:912
#define Assert(condition)
Definition: c.h:699
static int64 computeIterativeZipfian(TState *thread, int64 n, double s)
Definition: pgbench.c:882

◆ handle_sig_alarm()

static void handle_sig_alarm ( SIGNAL_ARGS  )
static

Definition at line 5956 of file pgbench.c.

Referenced by setalarm().

5957 {
5958  timer_exceeded = true;
5959 }
volatile bool timer_exceeded
Definition: pgbench.c:201

◆ initCreateFKeys()

static void initCreateFKeys ( PGconn con)
static

Definition at line 3725 of file pgbench.c.

References executeStatement(), i, and lengthof.

Referenced by runInitSteps().

3726 {
3727  static const char *const DDLKEYs[] = {
3728  "alter table pgbench_tellers add constraint pgbench_tellers_bid_fkey foreign key (bid) references pgbench_branches",
3729  "alter table pgbench_accounts add constraint pgbench_accounts_bid_fkey foreign key (bid) references pgbench_branches",
3730  "alter table pgbench_history add constraint pgbench_history_bid_fkey foreign key (bid) references pgbench_branches",
3731  "alter table pgbench_history add constraint pgbench_history_tid_fkey foreign key (tid) references pgbench_tellers",
3732  "alter table pgbench_history add constraint pgbench_history_aid_fkey foreign key (aid) references pgbench_accounts"
3733  };
3734  int i;
3735 
3736  fprintf(stderr, "creating foreign keys...\n");
3737  for (i = 0; i < lengthof(DDLKEYs); i++)
3738  {
3739  executeStatement(con, DDLKEYs[i]);
3740  }
3741 }
#define lengthof(array)
Definition: c.h:629
static void executeStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1066
int i

◆ initCreatePKeys()

static void initCreatePKeys ( PGconn con)
static

Definition at line 3690 of file pgbench.c.

References buffer, executeStatement(), i, lengthof, PQescapeIdentifier(), PQfreemem(), snprintf(), and strlcpy().

Referenced by runInitSteps().

3691 {
3692  static const char *const DDLINDEXes[] = {
3693  "alter table pgbench_branches add primary key (bid)",
3694  "alter table pgbench_tellers add primary key (tid)",
3695  "alter table pgbench_accounts add primary key (aid)"
3696  };
3697  int i;
3698 
3699  fprintf(stderr, "creating primary keys...\n");
3700  for (i = 0; i < lengthof(DDLINDEXes); i++)
3701  {
3702  char buffer[256];
3703 
3704  strlcpy(buffer, DDLINDEXes[i], sizeof(buffer));
3705 
3706  if (index_tablespace != NULL)
3707  {
3708  char *escape_tablespace;
3709 
3710  escape_tablespace = PQescapeIdentifier(con, index_tablespace,
3711  strlen(index_tablespace));
3712  snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer),
3713  " using index tablespace %s", escape_tablespace);
3714  PQfreemem(escape_tablespace);
3715  }
3716 
3717  executeStatement(con, buffer);
3718  }
3719 }
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define lengthof(array)
Definition: c.h:629
static void executeStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1066
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
Definition: fe-exec.c:3525
char * index_tablespace
Definition: pgbench.c:156
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
int i
void PQfreemem(void *ptr)
Definition: fe-exec.c:3251

◆ initCreateTables()

static void initCreateTables ( PGconn con)
static

Definition at line 3442 of file pgbench.c.

References buffer, executeStatement(), i, lengthof, PQescapeIdentifier(), PQfreemem(), SCALE_32BIT_THRESHOLD, and snprintf().

Referenced by runInitSteps().

3443 {
3444  /*
3445  * The scale factor at/beyond which 32-bit integers are insufficient for
3446  * storing TPC-B account IDs.
3447  *
3448  * Although the actual threshold is 21474, we use 20000 because it is
3449  * easier to document and remember, and isn't that far away from the real
3450  * threshold.
3451  */
3452 #define SCALE_32BIT_THRESHOLD 20000
3453 
3454  /*
3455  * Note: TPC-B requires at least 100 bytes per row, and the "filler"
3456  * fields in these table declarations were intended to comply with that.
3457  * The pgbench_accounts table complies with that because the "filler"
3458  * column is set to blank-padded empty string. But for all other tables
3459  * the columns default to NULL and so don't actually take any space. We
3460  * could fix that by giving them non-null default values. However, that
3461  * would completely break comparability of pgbench results with prior
3462  * versions. Since pgbench has never pretended to be fully TPC-B compliant
3463  * anyway, we stick with the historical behavior.
3464  */
3465  struct ddlinfo
3466  {
3467  const char *table; /* table name */
3468  const char *smcols; /* column decls if accountIDs are 32 bits */
3469  const char *bigcols; /* column decls if accountIDs are 64 bits */
3470  int declare_fillfactor;
3471  };
3472  static const struct ddlinfo DDLs[] = {
3473  {
3474  "pgbench_history",
3475  "tid int,bid int,aid int,delta int,mtime timestamp,filler char(22)",
3476  "tid int,bid int,aid bigint,delta int,mtime timestamp,filler char(22)",
3477  0
3478  },
3479  {
3480  "pgbench_tellers",
3481  "tid int not null,bid int,tbalance int,filler char(84)",
3482  "tid int not null,bid int,tbalance int,filler char(84)",
3483  1
3484  },
3485  {
3486  "pgbench_accounts",
3487  "aid int not null,bid int,abalance int,filler char(84)",
3488  "aid bigint not null,bid int,abalance int,filler char(84)",
3489  1
3490  },
3491  {
3492  "pgbench_branches",
3493  "bid int not null,bbalance int,filler char(88)",
3494  "bid int not null,bbalance int,filler char(88)",
3495  1
3496  }
3497  };
3498  int i;
3499 
3500  fprintf(stderr, "creating tables...\n");
3501 
3502  for (i = 0; i < lengthof(DDLs); i++)
3503  {
3504  char opts[256];
3505  char buffer[256];
3506  const struct ddlinfo *ddl = &DDLs[i];
3507  const char *cols;
3508 
3509  /* Construct new create table statement. */
3510  opts[0] = '\0';
3511  if (ddl->declare_fillfactor)
3512  snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
3513  " with (fillfactor=%d)", fillfactor);
3514  if (tablespace != NULL)
3515  {
3516  char *escape_tablespace;
3517 
3518  escape_tablespace = PQescapeIdentifier(con, tablespace,
3519  strlen(tablespace));
3520  snprintf(opts + strlen(opts), sizeof(opts) - strlen(opts),
3521  " tablespace %s", escape_tablespace);
3522  PQfreemem(escape_tablespace);
3523  }
3524 
3525  cols = (scale >= SCALE_32BIT_THRESHOLD) ? ddl->bigcols : ddl->smcols;
3526 
3527  snprintf(buffer, sizeof(buffer), "create%s table %s(%s)%s",
3528  unlogged_tables ? " unlogged" : "",
3529  ddl->table, cols, opts);
3530 
3531  executeStatement(con, buffer);
3532  }
3533 }
int scale
Definition: pgbench.c:120
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define lengthof(array)
Definition: c.h:629
static void executeStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1066
#define SCALE_32BIT_THRESHOLD
Definition: pgbench.c:177
char * PQescapeIdentifier(PGconn *conn, const char *str, size_t len)
Definition: fe-exec.c:3525
int fillfactor
Definition: pgbench.c:126
char * tablespace
Definition: pgbench.c:155
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
bool unlogged_tables
Definition: pgbench.c:131
int i
void PQfreemem(void *ptr)
Definition: fe-exec.c:3251

◆ initDropTables()

static void initDropTables ( PGconn con)
static

Definition at line 3423 of file pgbench.c.

References executeStatement().

Referenced by runInitSteps().

3424 {
3425  fprintf(stderr, "dropping old tables...\n");
3426 
3427  /*
3428  * We drop all the tables in one command, so that whether there are
3429  * foreign key dependencies or not doesn't matter.
3430  */
3431  executeStatement(con, "drop table if exists "
3432  "pgbench_accounts, "
3433  "pgbench_branches, "
3434  "pgbench_history, "
3435  "pgbench_tellers");
3436 }
static void executeStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1066

◆ initGenerateData()

static void initGenerateData ( PGconn con)
static

Definition at line 3539 of file pgbench.c.

References executeStatement(), i, INSTR_TIME_GET_DOUBLE, INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, INT64_FORMAT, LOG_STEP_SECONDS, naccounts, nbranches, ntellers, PGRES_COPY_IN, PQclear(), PQendcopy(), PQerrorMessage(), PQexec(), PQputline(), PQresultStatus(), scale, and snprintf().

Referenced by runInitSteps().

3540 {
3541  char sql[256];
3542  PGresult *res;
3543  int i;
3544  int64 k;
3545 
3546  /* used to track elapsed time and estimate of the remaining time */
3547  instr_time start,
3548  diff;
3549  double elapsed_sec,
3550  remaining_sec;
3551  int log_interval = 1;
3552 
3553  fprintf(stderr, "generating data...\n");
3554 
3555  /*
3556  * we do all of this in one transaction to enable the backend's
3557  * data-loading optimizations
3558  */
3559  executeStatement(con, "begin");
3560 
3561  /*
3562  * truncate away any old data, in one command in case there are foreign
3563  * keys
3564  */
3565  executeStatement(con, "truncate table "
3566  "pgbench_accounts, "
3567  "pgbench_branches, "
3568  "pgbench_history, "
3569  "pgbench_tellers");
3570 
3571  /*
3572  * fill branches, tellers, accounts in that order in case foreign keys
3573  * already exist
3574  */
3575  for (i = 0; i < nbranches * scale; i++)
3576  {
3577  /* "filler" column defaults to NULL */
3578  snprintf(sql, sizeof(sql),
3579  "insert into pgbench_branches(bid,bbalance) values(%d,0)",
3580  i + 1);
3581  executeStatement(con, sql);
3582  }
3583 
3584  for (i = 0; i < ntellers * scale; i++)
3585  {
3586  /* "filler" column defaults to NULL */
3587  snprintf(sql, sizeof(sql),
3588  "insert into pgbench_tellers(tid,bid,tbalance) values (%d,%d,0)",
3589  i + 1, i / ntellers + 1);
3590  executeStatement(con, sql);
3591  }
3592 
3593  /*
3594  * accounts is big enough to be worth using COPY and tracking runtime
3595  */
3596  res = PQexec(con, "copy pgbench_accounts from stdin");
3597  if (PQresultStatus(res) != PGRES_COPY_IN)
3598  {
3599  fprintf(stderr, "%s", PQerrorMessage(con));
3600  exit(1);
3601  }
3602  PQclear(res);
3603 
3604  INSTR_TIME_SET_CURRENT(start);
3605 
3606  for (k = 0; k < (int64) naccounts * scale; k++)
3607  {
3608  int64 j = k + 1;
3609 
3610  /* "filler" column defaults to blank padded empty string */
3611  snprintf(sql, sizeof(sql),
3612  INT64_FORMAT "\t" INT64_FORMAT "\t%d\t\n",
3613  j, k / naccounts + 1, 0);
3614  if (PQputline(con, sql))
3615  {
3616  fprintf(stderr, "PQputline failed\n");
3617  exit(1);
3618  }
3619 
3620  /*
3621  * If we want to stick with the original logging, print a message each
3622  * 100k inserted rows.
3623  */
3624  if ((!use_quiet) && (j % 100000 == 0))
3625  {
3626  INSTR_TIME_SET_CURRENT(diff);
3627  INSTR_TIME_SUBTRACT(diff, start);
3628 
3629  elapsed_sec = INSTR_TIME_GET_DOUBLE(diff);
3630  remaining_sec = ((double) scale * naccounts - j) * elapsed_sec / j;
3631 
3632  fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s)\n",
3633  j, (int64) naccounts * scale,
3634  (int) (((int64) j * 100) / (naccounts * (int64) scale)),
3635  elapsed_sec, remaining_sec);
3636  }
3637  /* let's not call the timing for each row, but only each 100 rows */
3638  else if (use_quiet && (j % 100 == 0))
3639  {
3640  INSTR_TIME_SET_CURRENT(diff);
3641  INSTR_TIME_SUBTRACT(diff, start);
3642 
3643  elapsed_sec = INSTR_TIME_GET_DOUBLE(diff);
3644  remaining_sec = ((double) scale * naccounts - j) * elapsed_sec / j;
3645 
3646  /* have we reached the next interval (or end)? */
3647  if ((j == scale * naccounts) || (elapsed_sec >= log_interval * LOG_STEP_SECONDS))
3648  {
3649  fprintf(stderr, INT64_FORMAT " of " INT64_FORMAT " tuples (%d%%) done (elapsed %.2f s, remaining %.2f s)\n",
3650  j, (int64) naccounts * scale,
3651  (int) (((int64) j * 100) / (naccounts * (int64) scale)), elapsed_sec, remaining_sec);
3652 
3653  /* skip to the next interval */
3654  log_interval = (int) ceil(elapsed_sec / LOG_STEP_SECONDS);
3655  }
3656  }
3657 
3658  }
3659  if (PQputline(con, "\\.\n"))
3660  {
3661  fprintf(stderr, "very last PQputline failed\n");
3662  exit(1);
3663  }
3664  if (PQendcopy(con))
3665  {
3666  fprintf(stderr, "PQendcopy failed\n");
3667  exit(1);
3668  }
3669 
3670  executeStatement(con, "commit");
3671 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6116
struct timeval instr_time
Definition: instr_time.h:147
int scale
Definition: pgbench.c:120
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:196
#define LOG_STEP_SECONDS
Definition: pgbench.c:104
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
bool use_quiet
Definition: pgbench.c:180
static void executeStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1066
int PQputline(PGconn *conn, const char *s)
Definition: fe-exec.c:2540
#define nbranches
Definition: pgbench.c:165
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:167
#define ntellers
Definition: pgbench.c:167
#define naccounts
Definition: pgbench.c:168
void PQclear(PGresult *res)
Definition: fe-exec.c:671
int PQendcopy(PGconn *conn)
Definition: fe-exec.c:2573
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:153
#define INT64_FORMAT
Definition: c.h:367
int i
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1897

◆ initSimpleStats()

static void initSimpleStats ( SimpleStats ss)
static

Definition at line 992 of file pgbench.c.

Referenced by initStats(), process_backslash_command(), and process_sql_command().

993 {
994  memset(ss, 0, sizeof(SimpleStats));
995 }

◆ initStats()

static void initStats ( StatsData sd,
time_t  start_time 
)
static

Definition at line 1032 of file pgbench.c.

References StatsData::cnt, initSimpleStats(), StatsData::lag, StatsData::latency, StatsData::skipped, start_time, and StatsData::start_time.

Referenced by doLog(), main(), ParseScript(), and threadRun().

1033 {
1034  sd->start_time = start_time;
1035  sd->cnt = 0;
1036  sd->skipped = 0;
1037  initSimpleStats(&sd->latency);
1038  initSimpleStats(&sd->lag);
1039 }
time_t start_time
Definition: pgbench.c:244
SimpleStats lag
Definition: pgbench.c:249
SimpleStats latency
Definition: pgbench.c:248
static time_t start_time
Definition: pg_ctl.c:96
int64 cnt
Definition: pgbench.c:245
int64 skipped
Definition: pgbench.c:246
static void initSimpleStats(SimpleStats *ss)
Definition: pgbench.c:992

◆ initVacuum()

static void initVacuum ( PGconn con)
static

Definition at line 3677 of file pgbench.c.

References executeStatement().

Referenced by runInitSteps().

3678 {
3679  fprintf(stderr, "vacuuming...\n");
3680  executeStatement(con, "vacuum analyze pgbench_branches");
3681  executeStatement(con, "vacuum analyze pgbench_tellers");
3682  executeStatement(con, "vacuum analyze pgbench_accounts");
3683  executeStatement(con, "vacuum analyze pgbench_history");
3684 }
static void executeStatement(PGconn *con, const char *sql)
Definition: pgbench.c:1066

◆ is_an_int()

static bool is_an_int ( const char *  str)
static

Definition at line 601 of file pgbench.c.

References generate_unaccent_rules::str.

Referenced by makeVariableValue().

602 {
603  const char *ptr = str;
604 
605  /* skip leading spaces; cast is consistent with strtoint64 */
606  while (*ptr && isspace((unsigned char) *ptr))
607  ptr++;
608 
609  /* skip sign */
610  if (*ptr == '+' || *ptr == '-')
611  ptr++;
612 
613  /* at least one digit */
614  if (*ptr && !isdigit((unsigned char) *ptr))
615  return false;
616 
617  /* eat all digits */
618  while (*ptr && isdigit((unsigned char) *ptr))
619  ptr++;
620 
621  /* must have reached end of string */
622  return *ptr == '\0';
623 }

◆ isLazyFunc()

static bool isLazyFunc ( PgBenchFunction  func)
static

Definition at line 1679 of file pgbench.c.

References PGBENCH_AND, PGBENCH_CASE, and PGBENCH_OR.

Referenced by evalFunc(), and evalLazyFunc().

1680 {
1681  return func == PGBENCH_AND || func == PGBENCH_OR || func == PGBENCH_CASE;
1682 }

◆ listAvailableScripts()

static void listAvailableScripts ( void  )
static

Definition at line 4404 of file pgbench.c.

References i, lengthof, and name.

Referenced by findBuiltin(), and main().

4405 {
4406  int i;
4407 
4408  fprintf(stderr, "Available builtin scripts:\n");
4409  for (i = 0; i < lengthof(builtin_script); i++)
4410  fprintf(stderr, "\t%s\n", builtin_script[i].name);
4411  fprintf(stderr, "\n");
4412 }
#define lengthof(array)
Definition: c.h:629
static const BuiltinScript builtin_script[]
Definition: pgbench.c:473
const char * name
Definition: encode.c:521
int i

◆ lookupCreateVariable()

static Variable* lookupCreateVariable ( CState st,
const char *  context,
char *  name 
)
static

Definition at line 1343 of file pgbench.c.

References lookupVariable(), Variable::name, CState::nvariables, pg_malloc(), pg_realloc(), pg_strdup(), Variable::svalue, valid_variable_name(), CState::variables, and CState::vars_sorted.

Referenced by putVariable(), and putVariableValue().

1344 {
1345  Variable *var;
1346 
1347  var = lookupVariable(st, name);
1348  if (var == NULL)
1349  {
1350  Variable *newvars;
1351 
1352  /*
1353  * Check for the name only when declaring a new variable to avoid
1354  * overhead.
1355  */
1356  if (!valid_variable_name(name))
1357  {
1358  fprintf(stderr, "%s: invalid variable name: \"%s\"\n",
1359  context, name);
1360  return NULL;
1361  }
1362 
1363  /* Create variable at the end of the array */
1364  if (st->variables)
1365  newvars = (Variable *) pg_realloc(st->variables,
1366  (st->nvariables + 1) * sizeof(Variable));
1367  else
1368  newvars = (Variable *) pg_malloc(sizeof(Variable));
1369 
1370  st->variables = newvars;
1371 
1372  var = &newvars[st->nvariables];
1373 
1374  var->name = pg_strdup(name);
1375  var->svalue = NULL;
1376  /* caller is expected to initialize remaining fields */
1377 
1378  st->nvariables++;
1379  /* we don't re-sort the array till we have to */
1380  st->vars_sorted = false;
1381  }
1382 
1383  return var;
1384 }
static Variable * lookupVariable(CState *st, char *name)
Definition: pgbench.c:1187
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
char * name
Definition: pgbench.c:215
static bool valid_variable_name(const char *name)
Definition: pgbench.c:1316
Variable * variables
Definition: pgbench.c:337
bool vars_sorted
Definition: pgbench.c:339
char * svalue
Definition: pgbench.c:216
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
const char * name
Definition: encode.c:521
int nvariables
Definition: pgbench.c:338

◆ lookupVariable()

static Variable* lookupVariable ( CState st,
char *  name 
)
static

Definition at line 1187 of file pgbench.c.

References compareVariableNames(), Variable::name, name, CState::nvariables, qsort, CState::variables, and CState::vars_sorted.

Referenced by evaluateExpr(), getVariable(), lookupCreateVariable(), and main().

1188 {
1189  Variable key;
1190 
1191  /* On some versions of Solaris, bsearch of zero items dumps core */
1192  if (st->nvariables <= 0)
1193  return NULL;
1194 
1195  /* Sort if we have to */
1196  if (!st->vars_sorted)
1197  {
1198  qsort((void *) st->variables, st->nvariables, sizeof(Variable),
1200  st->vars_sorted = true;
1201  }
1202 
1203  /* Now we can search */
1204  key.name = name;
1205  return (Variable *) bsearch((void *) &key,
1206  (void *) st->variables,
1207  st->nvariables,
1208  sizeof(Variable),
1210 }
char * name
Definition: pgbench.c:215
static int compareVariableNames(const void *v1, const void *v2)
Definition: pgbench.c:1179
Variable * variables
Definition: pgbench.c:337
bool vars_sorted
Definition: pgbench.c:339
const char * name
Definition: encode.c:521
int nvariables
Definition: pgbench.c:338
#define qsort(a, b, c, d)
Definition: port.h:421

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 4721 of file pgbench.c.

References _, Assert, checkInitSteps(), StatsData::cnt, ParsedScript::commands, conditional_stack_create(), TState::conn_time, CONNECTION_BAD, CState::cstack, ZipfCache::current, DEFAULT_INIT_STEPS, DEFAULT_NXACTS, disconnect_all(), doConnect(), ERRCODE_UNDEFINED_TABLE, findBuiltin(), get_progname(), getopt_long(), i, CState::id, initStats(), INSTR_TIME_ADD, INSTR_TIME_GET_MICROSEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SET_ZERO, INSTR_TIME_SUBTRACT, INVALID_THREAD, StatsData::lag, StatsData::latency, TState::latency_late, listAvailableScripts(), TState::logfile, login, lookupVariable(), MAXCLIENTS, mergeSimpleStats(), Variable::name, ZipfCache::nb_cells, nclients, no_argument, TState::nstate, nthreads, NUM_QUERYMODE, num_scripts, CState::nvariables, optarg, optind, ZipfCache::overflowCount, parseQuery(), parseScriptWeight(), PG_DIAG_SQLSTATE, pg_free(), pg_malloc(), pg_realloc(), pg_strdup(), PGBT_NO_VALUE, PGRES_TUPLES_OK, PQclear(), PQdb(), PQerrorMessage(), PQexec(), PQfinish(), PQgetvalue(), PQresultErrorField(), PQresultStatus(), PQstatus(), printResults(), process_builtin(), process_file(), putVariable(), putVariableInt(), putVariableValue(), QUERY_SIMPLE, random(), TState::random_state, required_argument, runInitSteps(), set_random_seed(), setalarm(), StatsData::skipped, SQL_COMMAND, start_time, TState::start_time, TState::state, TState::stats, strerror(), Variable::svalue, TState::thread, threadRun(), TState::tid, tryExecuteStatement(), PgBenchValue::type, generate_unaccent_rules::type, usage(), Variable::value, CState::variables, and TState::zipf_cache.

4722 {
4723  static struct option long_options[] = {
4724  /* systematic long/short named options */
4725  {"builtin", required_argument, NULL, 'b'},
4726  {"client", required_argument, NULL, 'c'},
4727  {"connect", no_argument, NULL, 'C'},
4728  {"debug", no_argument, NULL, 'd'},
4729  {"define", required_argument, NULL, 'D'},
4730  {"file", required_argument, NULL, 'f'},
4731  {"fillfactor", required_argument, NULL, 'F'},
4732  {"host", required_argument, NULL, 'h'},
4733  {"initialize", no_argument, NULL, 'i'},
4734  {"init-steps", required_argument, NULL, 'I'},
4735  {"jobs", required_argument, NULL, 'j'},
4736  {"log", no_argument, NULL, 'l'},
4737  {"latency-limit", required_argument, NULL, 'L'},
4738  {"no-vacuum", no_argument, NULL, 'n'},
4739  {"port", required_argument, NULL, 'p'},
4740  {"progress", required_argument, NULL, 'P'},
4741  {"protocol", required_argument, NULL, 'M'},
4742  {"quiet", no_argument, NULL, 'q'},
4743  {"report-latencies", no_argument, NULL, 'r'},
4744  {"rate", required_argument, NULL, 'R'},
4745  {"scale", required_argument, NULL, 's'},
4746  {"select-only", no_argument, NULL, 'S'},
4747  {"skip-some-updates", no_argument, NULL, 'N'},
4748  {"time", required_argument, NULL, 'T'},
4749  {"transactions", required_argument, NULL, 't'},
4750  {"username", required_argument, NULL, 'U'},
4751  {"vacuum-all", no_argument, NULL, 'v'},
4752  /* long-named only options */
4753  {"unlogged-tables", no_argument, NULL, 1},
4754  {"tablespace", required_argument, NULL, 2},
4755  {"index-tablespace", required_argument, NULL, 3},
4756  {"sampling-rate", required_argument, NULL, 4},
4757  {"aggregate-interval", required_argument, NULL, 5},
4758  {"progress-timestamp", no_argument, NULL, 6},
4759  {"log-prefix", required_argument, NULL, 7},
4760  {"foreign-keys", no_argument, NULL, 8},
4761  {"random-seed", required_argument, NULL, 9},
4762  {NULL, 0, NULL, 0}
4763  };
4764 
4765  int c;
4766  bool is_init_mode = false; /* initialize mode? */
4767  char *initialize_steps = NULL;
4768  bool foreign_keys = false;
4769  bool is_no_vacuum = false;
4770  bool do_vacuum_accounts = false; /* vacuum accounts table? */
4771  int optindex;
4772  bool scale_given = false;
4773 
4774  bool benchmarking_option_set = false;
4775  bool initialization_option_set = false;
4776  bool internal_script_used = false;
4777 
4778  CState *state; /* status of clients */
4779  TState *threads; /* array of thread */
4780 
4781  instr_time start_time; /* start up time */
4782  instr_time total_time;
4783  instr_time conn_total_time;
4784  int64 latency_late = 0;
4785  StatsData stats;
4786  int weight;
4787 
4788  int i;
4789  int nclients_dealt;
4790 
4791 #ifdef HAVE_GETRLIMIT
4792  struct rlimit rlim;
4793 #endif
4794 
4795  PGconn *con;
4796  PGresult *res;
4797  char *env;
4798 
4799  progname = get_progname(argv[0]);
4800 
4801  if (argc > 1)
4802  {
4803  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
4804  {
4805  usage();
4806  exit(0);
4807  }
4808  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
4809  {
4810  puts("pgbench (PostgreSQL) " PG_VERSION);
4811  exit(0);
4812  }
4813  }
4814 
4815 #ifdef WIN32
4816  /* stderr is buffered on Win32. */
4817  setvbuf(stderr, NULL, _IONBF, 0);
4818 #endif
4819 
4820  if ((env = getenv("PGHOST")) != NULL && *env != '\0')
4821  pghost = env;
4822  if ((env = getenv("PGPORT")) != NULL && *env != '\0')
4823  pgport = env;
4824  else if ((env = getenv("PGUSER")) != NULL && *env != '\0')
4825  login = env;
4826 
4827  state = (CState *) pg_malloc(sizeof(CState));
4828  memset(state, 0, sizeof(CState));
4829 
4830  /* set random seed early, because it may be used while parsing scripts. */
4831  if (!set_random_seed(getenv("PGBENCH_RANDOM_SEED")))
4832  {
4833  fprintf(stderr, "error while setting random seed from PGBENCH_RANDOM_SEED environment variable\n");
4834  exit(1);
4835  }
4836 
4837  while ((c = getopt_long(argc, argv, "iI:h:nvp:dqb:SNc:j:Crs:t:T:U:lf:D:F:M:P:R:L:", long_options, &optindex)) != -1)
4838  {
4839  char *script;
4840 
4841  switch (c)
4842  {
4843  case 'i':
4844  is_init_mode = true;
4845  break;
4846  case 'I':
4847  if (initialize_steps)
4848  pg_free(initialize_steps);
4849  initialize_steps = pg_strdup(optarg);
4850  checkInitSteps(initialize_steps);
4851  initialization_option_set = true;
4852  break;
4853  case 'h':
4854  pghost = pg_strdup(optarg);
4855  break;
4856  case 'n':
4857  is_no_vacuum = true;
4858  break;
4859  case 'v':
4860  benchmarking_option_set = true;
4861  do_vacuum_accounts = true;
4862  break;
4863  case 'p':
4864  pgport = pg_strdup(optarg);
4865  break;
4866  case 'd':
4867  debug++;
4868  break;
4869  case 'c':
4870  benchmarking_option_set = true;
4871  nclients = atoi(optarg);
4872  if (nclients <= 0 || nclients > MAXCLIENTS)
4873  {
4874  fprintf(stderr, "invalid number of clients: \"%s\"\n",
4875  optarg);
4876  exit(1);
4877  }
4878 #ifdef HAVE_GETRLIMIT
4879 #ifdef RLIMIT_NOFILE /* most platforms use RLIMIT_NOFILE */
4880  if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
4881 #else /* but BSD doesn't ... */
4882  if (getrlimit(RLIMIT_OFILE, &rlim) == -1)
4883 #endif /* RLIMIT_NOFILE */
4884  {
4885  fprintf(stderr, "getrlimit failed: %s\n", strerror(errno));
4886  exit(1);
4887  }
4888  if (rlim.rlim_cur < nclients + 3)
4889  {
4890  fprintf(stderr, "need at least %d open files, but system limit is %ld\n",
4891  nclients + 3, (long) rlim.rlim_cur);
4892  fprintf(stderr, "Reduce number of clients, or use limit/ulimit to increase the system limit.\n");
4893  exit(1);
4894  }
4895 #endif /* HAVE_GETRLIMIT */
4896  break;
4897  case 'j': /* jobs */
4898  benchmarking_option_set = true;
4899  nthreads = atoi(optarg);
4900  if (nthreads <= 0)
4901  {
4902  fprintf(stderr, "invalid number of threads: \"%s\"\n",
4903  optarg);
4904  exit(1);
4905  }
4906 #ifndef ENABLE_THREAD_SAFETY
4907  if (nthreads != 1)
4908  {
4909  fprintf(stderr, "threads are not supported on this platform; use -j1\n");
4910  exit(1);
4911  }
4912 #endif /* !ENABLE_THREAD_SAFETY */
4913  break;
4914  case 'C':
4915  benchmarking_option_set = true;
4916  is_connect = true;
4917  break;
4918  case 'r':
4919  benchmarking_option_set = true;
4920  is_latencies = true;
4921  break;
4922  case 's':
4923  scale_given = true;
4924  scale = atoi(optarg);
4925  if (scale <= 0)
4926  {
4927  fprintf(stderr, "invalid scaling factor: \"%s\"\n", optarg);
4928  exit(1);
4929  }
4930  break;
4931  case 't':
4932  benchmarking_option_set = true;
4933  nxacts = atoi(optarg);
4934  if (nxacts <= 0)
4935  {
4936  fprintf(stderr, "invalid number of transactions: \"%s\"\n",
4937  optarg);
4938  exit(1);
4939  }
4940  break;
4941  case 'T':
4942  benchmarking_option_set = true;
4943  duration = atoi(optarg);
4944  if (duration <= 0)
4945  {
4946  fprintf(stderr, "invalid duration: \"%s\"\n", optarg);
4947  exit(1);
4948  }
4949  break;
4950  case 'U':
4951  login = pg_strdup(optarg);
4952  break;
4953  case 'l':
4954  benchmarking_option_set = true;
4955  use_log = true;
4956  break;
4957  case 'q':
4958  initialization_option_set = true;
4959  use_quiet = true;
4960  break;
4961  case 'b':
4962  if (strcmp(optarg, "list") == 0)
4963  {
4965  exit(0);
4966  }
4967  weight = parseScriptWeight(optarg, &script);
4968  process_builtin(findBuiltin(script), weight);
4969  benchmarking_option_set = true;
4970  internal_script_used = true;
4971  break;
4972  case 'S':
4973  process_builtin(findBuiltin("select-only"), 1);
4974  benchmarking_option_set = true;
4975  internal_script_used = true;
4976  break;
4977  case 'N':
4978  process_builtin(findBuiltin("simple-update"), 1);
4979  benchmarking_option_set = true;
4980  internal_script_used = true;
4981  break;
4982  case 'f':
4983  weight = parseScriptWeight(optarg, &script);
4984  process_file(script, weight);
4985  benchmarking_option_set = true;
4986  break;
4987  case 'D':
4988  {
4989  char *p;
4990 
4991  benchmarking_option_set = true;
4992 
4993  if ((p = strchr(optarg, '=')) == NULL || p == optarg || *(p + 1) == '\0')
4994  {
4995  fprintf(stderr, "invalid variable definition: \"%s\"\n",
4996  optarg);
4997  exit(1);
4998  }
4999 
5000  *p++ = '\0';
5001  if (!putVariable(&state[0], "option", optarg, p))
5002  exit(1);
5003  }
5004  break;
5005  case 'F':
5006  initialization_option_set = true;
5007  fillfactor = atoi(optarg);
5008  if (fillfactor < 10 || fillfactor > 100)
5009  {
5010  fprintf(stderr, "invalid fillfactor: \"%s\"\n", optarg);
5011  exit(1);
5012  }
5013  break;
5014  case 'M':
5015  benchmarking_option_set = true;
5016  for (querymode = 0; querymode < NUM_QUERYMODE; querymode++)
5017  if (strcmp(optarg, QUERYMODE[querymode]) == 0)
5018  break;
5019  if (querymode >= NUM_QUERYMODE)
5020  {
5021  fprintf(stderr, "invalid query mode (-M): \"%s\"\n",
5022  optarg);
5023  exit(1);
5024  }
5025  break;
5026  case 'P':
5027  benchmarking_option_set = true;
5028  progress = atoi(optarg);
5029  if (progress <= 0)
5030  {
5031  fprintf(stderr, "invalid thread progress delay: \"%s\"\n",
5032  optarg);
5033  exit(1);
5034  }
5035  break;
5036  case 'R':
5037  {
5038  /* get a double from the beginning of option value */
5039  double throttle_value = atof(optarg);
5040 
5041  benchmarking_option_set = true;
5042 
5043  if (throttle_value <= 0.0)
5044  {
5045  fprintf(stderr, "invalid rate limit: \"%s\"\n", optarg);
5046  exit(1);
5047  }
5048  /* Invert rate limit into a time offset */
5049  throttle_delay = (int64) (1000000.0 / throttle_value);
5050  }
5051  break;
5052  case 'L':
5053  {
5054  double limit_ms = atof(optarg);
5055 
5056  if (limit_ms <= 0.0)
5057  {
5058  fprintf(stderr, "invalid latency limit: \"%s\"\n",
5059  optarg);
5060  exit(1);
5061  }
5062  benchmarking_option_set = true;
5063  latency_limit = (int64) (limit_ms * 1000);
5064  }
5065  break;
5066  case 1: /* unlogged-tables */
5067  initialization_option_set = true;
5068  unlogged_tables = true;
5069  break;
5070  case 2: /* tablespace */
5071  initialization_option_set = true;
5073  break;
5074  case 3: /* index-tablespace */
5075  initialization_option_set = true;
5077  break;
5078  case 4: /* sampling-rate */
5079  benchmarking_option_set = true;
5080  sample_rate = atof(optarg);
5081  if (sample_rate <= 0.0 || sample_rate > 1.0)
5082  {
5083  fprintf(stderr, "invalid sampling rate: \"%s\"\n", optarg);
5084  exit(1);
5085  }
5086  break;
5087  case 5: /* aggregate-interval */
5088  benchmarking_option_set = true;
5089  agg_interval = atoi(optarg);
5090  if (agg_interval <= 0)
5091  {
5092  fprintf(stderr, "invalid number of seconds for aggregation: \"%s\"\n",
5093  optarg);
5094  exit(1);
5095  }
5096  break;
5097  case 6: /* progress-timestamp */
5098  progress_timestamp = true;
5099  benchmarking_option_set = true;
5100  break;
5101  case 7: /* log-prefix */
5102  benchmarking_option_set = true;
5104  break;
5105  case 8: /* foreign-keys */
5106  initialization_option_set = true;
5107  foreign_keys = true;
5108  break;
5109  case 9: /* random-seed */
5110  benchmarking_option_set = true;
5111  if (!set_random_seed(optarg))
5112  {
5113  fprintf(stderr, "error while setting random seed from --random-seed option\n");
5114  exit(1);
5115  }
5116  break;
5117  default:
5118  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
5119  exit(1);
5120  break;
5121  }
5122  }
5123 
5124  /* set default script if none */
5125  if (num_scripts == 0 && !is_init_mode)
5126  {
5127  process_builtin(findBuiltin("tpcb-like"), 1);
5128  benchmarking_option_set = true;
5129  internal_script_used = true;
5130  }
5131 
5132  /* if not simple query mode, parse the script(s) to find parameters */
5133  if (querymode != QUERY_SIMPLE)
5134  {
5135  for (i = 0; i < num_scripts; i++)
5136  {
5137  Command **commands = sql_script[i].commands;
5138  int j;
5139 
5140  for (j = 0; commands[j] != NULL; j++)
5141  {
5142  if (commands[j]->type != SQL_COMMAND)
5143  continue;
5144  if (!parseQuery(commands[j]))
5145  exit(1);
5146  }
5147  }
5148  }
5149 
5150  /* compute total_weight */
5151  for (i = 0; i < num_scripts; i++)
5152  /* cannot overflow: weight is 32b, total_weight 64b */
5153  total_weight += sql_script[i].weight;
5154 
5155  if (total_weight == 0 && !is_init_mode)
5156  {
5157  fprintf(stderr, "total script weight must not be zero\n");
5158  exit(1);
5159  }
5160 
5161  /* show per script stats if several scripts are used */
5162  if (num_scripts > 1)
5163  per_script_stats = true;
5164 
5165  /*
5166  * Don't need more threads than there are clients. (This is not merely an
5167  * optimization; throttle_delay is calculated incorrectly below if some
5168  * threads have no clients assigned to them.)
5169  */
5170  if (nthreads > nclients)
5171  nthreads = nclients;
5172 
5173  /* compute a per thread delay */
5175 
5176  if (argc > optind)
5177  dbName = argv[optind];
5178  else
5179  {
5180  if ((env = getenv("PGDATABASE")) != NULL && *env != '\0')
5181  dbName = env;
5182  else if (login != NULL && *login != '\0')
5183  dbName = login;
5184  else
5185  dbName = "";
5186  }
5187 
5188  if (is_init_mode)
5189  {
5190  if (benchmarking_option_set)
5191  {
5192  fprintf(stderr, "some of the specified options cannot be used in initialization (-i) mode\n");
5193  exit(1);
5194  }
5195 
5196  if (initialize_steps == NULL)
5197  initialize_steps = pg_strdup(DEFAULT_INIT_STEPS);
5198 
5199  if (is_no_vacuum)
5200  {
5201  /* Remove any vacuum step in initialize_steps */
5202  char *p;
5203 
5204  while ((p = strchr(initialize_steps, 'v')) != NULL)
5205  *p = ' ';
5206  }
5207 
5208  if (foreign_keys)
5209  {
5210  /* Add 'f' to end of initialize_steps, if not already there */
5211  if (strchr(initialize_steps, 'f') == NULL)
5212  {
5213  initialize_steps = (char *)
5214  pg_realloc(initialize_steps,
5215  strlen(initialize_steps) + 2);
5216  strcat(initialize_steps, "f");
5217  }
5218  }
5219 
5220  runInitSteps(initialize_steps);
5221  exit(0);
5222  }
5223  else
5224  {
5225  if (initialization_option_set)
5226  {
5227  fprintf(stderr, "some of the specified options cannot be used in benchmarking mode\n");
5228  exit(1);
5229  }
5230  }
5231 
5232  if (nxacts > 0 && duration > 0)
5233  {
5234  fprintf(stderr, "specify either a number of transactions (-t) or a duration (-T), not both\n");
5235  exit(1);
5236  }
5237 
5238  /* Use DEFAULT_NXACTS if neither nxacts nor duration is specified. */
5239  if (nxacts <= 0 && duration <= 0)
5241 
5242  /* --sampling-rate may be used only with -l */
5243  if (sample_rate > 0.0 && !use_log)
5244  {
5245  fprintf(stderr, "log sampling (--sampling-rate) is allowed only when logging transactions (-l)\n");
5246  exit(1);
5247  }
5248 
5249  /* --sampling-rate may not be used with --aggregate-interval */
5250  if (sample_rate > 0.0 && agg_interval > 0)
5251  {
5252  fprintf(stderr, "log sampling (--sampling-rate) and aggregation (--aggregate-interval) cannot be used at the same time\n");
5253  exit(1);
5254  }
5255 
5256  if (agg_interval > 0 && !use_log)
5257  {
5258  fprintf(stderr, "log aggregation is allowed only when actually logging transactions\n");
5259  exit(1);
5260  }
5261 
5262  if (!use_log && logfile_prefix)
5263  {
5264  fprintf(stderr, "log file prefix (--log-prefix) is allowed only when logging transactions (-l)\n");
5265  exit(1);
5266  }
5267 
5268  if (duration > 0 && agg_interval > duration)
5269  {
5270  fprintf(stderr, "number of seconds for aggregation (%d) must not be higher than test duration (%d)\n", agg_interval, duration);
5271  exit(1);
5272  }
5273 
5274  if (duration > 0 && agg_interval > 0 && duration % agg_interval != 0)
5275  {
5276  fprintf(stderr, "duration (%d) must be a multiple of aggregation interval (%d)\n", duration, agg_interval);
5277  exit(1);
5278  }
5279 
5280  if (progress_timestamp && progress == 0)
5281  {
5282  fprintf(stderr, "--progress-timestamp is allowed only under --progress\n");
5283  exit(1);
5284  }
5285 
5286  /*
5287  * save main process id in the global variable because process id will be
5288  * changed after fork.
5289  */
5290  main_pid = (int) getpid();
5291 
5292  if (nclients > 1)
5293  {
5294  state = (CState *) pg_realloc(state, sizeof(CState) * nclients);
5295  memset(state + 1, 0, sizeof(CState) * (nclients - 1));
5296 
5297  /* copy any -D switch values to all clients */
5298  for (i = 1; i < nclients; i++)
5299  {
5300  int j;
5301 
5302  state[i].id = i;
5303  for (j = 0; j < state[0].nvariables; j++)
5304  {
5305  Variable *var = &state[0].variables[j];
5306 
5307  if (var->value.type != PGBT_NO_VALUE)
5308  {
5309  if (!putVariableValue(&state[i], "startup",
5310  var->name, &var->value))
5311  exit(1);
5312  }
5313  else
5314  {
5315  if (!putVariable(&state[i], "startup",
5316  var->name, var->svalue))
5317  exit(1);
5318  }
5319  }
5320  }
5321  }
5322 
5323  /* other CState initializations */
5324  for (i = 0; i < nclients; i++)
5325  {
5326  state[i].cstack = conditional_stack_create();
5327  }
5328 
5329  if (debug)
5330  {
5331  if (duration <= 0)
5332  printf("pghost: %s pgport: %s nclients: %d nxacts: %d dbName: %s\n",
5333  pghost, pgport, nclients, nxacts, dbName);
5334  else
5335  printf("pghost: %s pgport: %s nclients: %d duration: %d dbName: %s\n",
5336  pghost, pgport, nclients, duration, dbName);
5337  }
5338 
5339  /* opening connection... */
5340  con = doConnect();
5341  if (con == NULL)
5342  exit(1);
5343 
5344  if (PQstatus(con) == CONNECTION_BAD)
5345  {
5346  fprintf(stderr, "connection to database \"%s\" failed\n", dbName);
5347  fprintf(stderr, "%s", PQerrorMessage(con));
5348  exit(1);
5349  }
5350 
5351  if (internal_script_used)
5352  {
5353  /*
5354  * get the scaling factor that should be same as count(*) from
5355  * pgbench_branches if this is not a custom query
5356  */
5357  res = PQexec(con, "select count(*) from pgbench_branches");
5358  if (PQresultStatus(res) != PGRES_TUPLES_OK)
5359  {
5360  char *sqlState = PQresultErrorField(res, PG_DIAG_SQLSTATE);
5361 
5362  fprintf(stderr, "%s", PQerrorMessage(con));
5363  if (sqlState && strcmp(sqlState, ERRCODE_UNDEFINED_TABLE) == 0)
5364  {
5365  fprintf(stderr, "Perhaps you need to do initialization (\"pgbench -i\") in database \"%s\"\n", PQdb(con));
5366  }
5367 
5368  exit(1);
5369  }
5370  scale = atoi(PQgetvalue(res, 0, 0));
5371  if (scale < 0)
5372  {
5373  fprintf(stderr, "invalid count(*) from pgbench_branches: \"%s\"\n",
5374  PQgetvalue(res, 0, 0));
5375  exit(1);
5376  }
5377  PQclear(res);
5378 
5379  /* warn if we override user-given -s switch */
5380  if (scale_given)
5381  fprintf(stderr,
5382  "scale option ignored, using count from pgbench_branches table (%d)\n",
5383  scale);
5384  }
5385 
5386  /*
5387  * :scale variables normally get -s or database scale, but don't override
5388  * an explicit -D switch
5389  */
5390  if (lookupVariable(&state[0], "scale") == NULL)
5391  {
5392  for (i = 0; i < nclients; i++)
5393  {
5394  if (!putVariableInt(&state[i], "startup", "scale", scale))
5395  exit(1);
5396  }
5397  }
5398 
5399  /*
5400  * Define a :client_id variable that is unique per connection. But don't
5401  * override an explicit -D switch.
5402  */
5403  if (lookupVariable(&state[0], "client_id") == NULL)
5404  {
5405  for (i = 0; i < nclients; i++)
5406  if (!putVariableInt(&state[i], "startup", "client_id", i))
5407  exit(1);
5408  }
5409 
5410  /* set default seed for hash functions */
5411  if (lookupVariable(&state[0], "default_seed") == NULL)
5412  {
5413  uint64 seed = ((uint64) (random() & 0xFFFF) << 48) |
5414  ((uint64) (random() & 0xFFFF) << 32) |
5415  ((uint64) (random() & 0xFFFF) << 16) |
5416  (uint64) (random() & 0xFFFF);
5417 
5418  for (i = 0; i < nclients; i++)
5419  if (!putVariableInt(&state[i], "startup", "default_seed", (int64) seed))
5420  exit(1);
5421  }
5422 
5423  /* set random seed unless overwritten */
5424  if (lookupVariable(&state[0], "random_seed") == NULL)
5425  {
5426  for (i = 0; i < nclients; i++)
5427  if (!putVariableInt(&state[i], "startup", "random_seed", random_seed))
5428  exit(1);
5429  }
5430 
5431  if (!is_no_vacuum)
5432  {
5433  fprintf(stderr, "starting vacuum...");
5434  tryExecuteStatement(con, "vacuum pgbench_branches");
5435  tryExecuteStatement(con, "vacuum pgbench_tellers");
5436  tryExecuteStatement(con, "truncate pgbench_history");
5437  fprintf(stderr, "end.\n");
5438 
5439  if (do_vacuum_accounts)
5440  {
5441  fprintf(stderr, "starting vacuum pgbench_accounts...");
5442  tryExecuteStatement(con, "vacuum analyze pgbench_accounts");
5443  fprintf(stderr, "end.\n");
5444  }
5445  }
5446  PQfinish(con);
5447 
5448  /* set up thread data structures */
5449  threads = (TState *) pg_malloc(sizeof(TState) * nthreads);
5450  nclients_dealt = 0;
5451 
5452  for (i = 0; i < nthreads; i++)
5453  {
5454  TState *thread = &threads[i];
5455 
5456  thread->tid = i;
5457  thread->state = &state[nclients_dealt];
5458  thread->nstate =
5459  (nclients - nclients_dealt + nthreads - i - 1) / (nthreads - i);
5460  thread->random_state[0] = random();
5461  thread->random_state[1] = random();
5462  thread->random_state[2] = random();
5463  thread->logfile = NULL; /* filled in later */
5464  thread->latency_late = 0;
5465  thread->zipf_cache.nb_cells = 0;
5466  thread->zipf_cache.current = 0;
5467  thread->zipf_cache.overflowCount = 0;
5468  initStats(&thread->stats, 0);
5469 
5470  nclients_dealt += thread->nstate;
5471  }
5472 
5473  /* all clients must be assigned to a thread */
5474  Assert(nclients_dealt == nclients);
5475 
5476  /* get start up time */
5477  INSTR_TIME_SET_CURRENT(start_time);
5478 
5479  /* set alarm if duration is specified. */
5480  if (duration > 0)
5481  setalarm(duration);
5482 
5483  /* start threads */
5484 #ifdef ENABLE_THREAD_SAFETY
5485  for (i = 0; i < nthreads; i++)
5486  {
5487  TState *thread = &threads[i];
5488 
5490 
5491  /* compute when to stop */
5492  if (duration > 0)
5494  (int64) 1000000 * duration;
5495 
5496  /* the first thread (i = 0) is executed by main thread */
5497  if (i > 0)
5498  {
5499  int err = pthread_create(&thread->thread, NULL, threadRun, thread);
5500 
5501  if (err != 0 || thread->thread == INVALID_THREAD)
5502  {
5503  fprintf(stderr, "could not create thread: %s\n", strerror(err));
5504  exit(1);
5505  }
5506  }
5507  else
5508  {
5509  thread->thread = INVALID_THREAD;
5510  }
5511  }
5512 #else
5513  INSTR_TIME_SET_CURRENT(threads[0].start_time);
5514  /* compute when to stop */
5515  if (duration > 0)
5516  end_time = INSTR_TIME_GET_MICROSEC(threads[0].start_time) +
5517  (int64) 1000000 * duration;
5518  threads[0].thread = INVALID_THREAD;
5519 #endif /* ENABLE_THREAD_SAFETY */
5520 
5521  /* wait for threads and accumulate results */
5522  initStats(&stats, 0);
5523  INSTR_TIME_SET_ZERO(conn_total_time);
5524  for (i = 0; i < nthreads; i++)
5525  {
5526  TState *thread = &threads[i];
5527 
5528 #ifdef ENABLE_THREAD_SAFETY
5529  if (threads[i].thread == INVALID_THREAD)
5530  /* actually run this thread directly in the main thread */
5531  (void) threadRun(thread);
5532  else
5533  /* wait of other threads. should check that 0 is returned? */
5534  pthread_join(thread->thread, NULL);
5535 #else
5536  (void) threadRun(thread);
5537 #endif /* ENABLE_THREAD_SAFETY */
5538 
5539  /* aggregate thread level stats */
5540  mergeSimpleStats(&stats.latency, &thread->stats.latency);
5541  mergeSimpleStats(&stats.lag, &thread->stats.lag);
5542  stats.cnt += thread->stats.cnt;
5543  stats.skipped += thread->stats.skipped;
5544  latency_late += thread->latency_late;
5545  INSTR_TIME_ADD(conn_total_time, thread->conn_time);
5546  }
5547  disconnect_all(state, nclients);
5548 
5549  /*
5550  * XXX We compute results as though every client of every thread started
5551  * and finished at the same time. That model can diverge noticeably from
5552  * reality for a short benchmark run involving relatively many threads.
5553  * The first thread may process notably many transactions before the last
5554  * thread begins. Improving the model alone would bring limited benefit,
5555  * because performance during those periods of partial thread count can
5556  * easily exceed steady state performance. This is one of the many ways
5557  * short runs convey deceptive performance figures.
5558  */
5559  INSTR_TIME_SET_CURRENT(total_time);
5560  INSTR_TIME_SUBTRACT(total_time, start_time);
5561  printResults(threads, &stats, total_time, conn_total_time, latency_late);
5562 
5563  return 0;
5564 }
static void checkInitSteps(const char *initialize_steps)
Definition: pgbench.c:3751
static void printResults(TState *threads, StatsData *total, instr_time total_time, instr_time conn_total_time, int64 latency_late)
Definition: pgbench.c:4532
static const BuiltinScript * findBuiltin(const char *name)
Definition: pgbench.c:4416
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6116
double sample_rate
Definition: pgbench.c:136
static Variable * lookupVariable(CState *st, char *name)
Definition: pgbench.c:1187
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:62
#define INVALID_THREAD
Definition: pgbench.c:405
int id
Definition: pgbench.c:329
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
static int num_scripts
Definition: pgbench.c:459
unsigned short random_state[3]
Definition: pgbench.c:392
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
static void listAvailableScripts(void)
Definition: pgbench.c:4404
char * name
Definition: pgbench.c:215
int nclients
Definition: pgbench.c:186
const char * get_progname(const char *argv0)
Definition: path.c:453
int nb_cells
Definition: pgbench.c:378
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
long random(void)
Definition: random.c:22
static int parseScriptWeight(const char *option, char **script)
Definition: pgbench.c:4453
#define DEFAULT_INIT_STEPS
Definition: pgbench.c:102
struct timeval instr_time
Definition: instr_time.h:147
int64 latency_late
Definition: pgbench.c:402
SimpleStats lag
Definition: pgbench.c:249
static void initStats(StatsData *sd, time_t start_time)
Definition: pgbench.c:1032
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3638
int scale
Definition: pgbench.c:120
#define INSTR_TIME_SET_ZERO(t)
Definition: instr_time.h:151
bool use_log
Definition: pgbench.c:179
static bool putVariable(CState *st, const char *context, char *name, const char *value)
Definition: pgbench.c:1389
SimpleStats latency
Definition: pgbench.c:248
uint64 current
Definition: pgbench.c:376
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
static void process_file(const char *filename, int weight)
Definition: pgbench.c:4363
bool per_script_stats
Definition: pgbench.c:183
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
bool use_quiet
Definition: pgbench.c:180
int duration
Definition: pgbench.c:113
ConditionalStack cstack
Definition: pgbench.c:331
static time_t start_time
Definition: pg_ctl.c:96
bool is_connect
Definition: pgbench.c:188
Variable * variables
Definition: pgbench.c:337
int nstate
Definition: pgbench.c:391
static const char * QUERYMODE[]
Definition: pgbench.c:436
int64 end_time
Definition: pgbench.c:114
#define required_argument
Definition: getopt_long.h:25
FILE * logfile
Definition: pgbench.c:394
static void mergeSimpleStats(SimpleStats *acc, SimpleStats *ss)
Definition: pgbench.c:1016
int optind
Definition: getopt.c:51
int64 cnt
Definition: pgbench.c:245
CState * state
Definition: pgbench.c:390
int fillfactor
Definition: pgbench.c:126
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:167
static int debug
Definition: pgbench.c:463
ZipfCache zipf_cache
Definition: pgbench.c:395
char * svalue
Definition: pgbench.c:216
char * c
int nxacts
Definition: pgbench.c:112
#define INSTR_TIME_ADD(x, y)
Definition: instr_time.h:155
static void disconnect_all(CState *state, int length)
Definition: pgbench.c:3411
char * tablespace
Definition: pgbench.c:155
static void usage(void)
Definition: pgbench.c:537
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
instr_time start_time
Definition: pgbench.c:399
char * index_tablespace
Definition: pgbench.c:156
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
int nthreads
Definition: pgbench.c:187
static ParsedScript sql_script[MAX_SCRIPTS]
Definition: pgbench.c:458
static bool parseQuery(Command *cmd)
Definition: pgbench.c:3826
int64 skipped
Definition: pgbench.c:246
static int64 total_weight
Definition: pgbench.c:461
PgBenchValue value
Definition: pgbench.c:217
char * pghost
Definition: pgbench.c:192
int progress
Definition: pgbench.c:184
#define no_argument
Definition: getopt_long.h:24
ConditionalStack conditional_stack_create(void)
Definition: conditional.c:18
int64 random_seed
Definition: pgbench.c:159
static bool putVariableInt(CState *st, const char *context, char *name, int64 value)
Definition: pgbench.c:1432
#define SQL_COMMAND
Definition: pgbench.c:410
static void * threadRun(void *arg)
Definition: pgbench.c:5567
#define MAXCLIENTS
Definition: pgbench.c:99
void PQclear(PGresult *res)
Definition: fe-exec.c:671
bool progress_timestamp
Definition: pgbench.c:185
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:5983
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2709
static PGconn * doConnect(void)
Definition: pgbench.c:1096
#define Assert(condition)
Definition: c.h:699
Definition: regguts.h:298
const char * progname
Definition: pgbench.c:197
char * logfile_prefix
Definition: pgbench.c:196
#define INSTR_TIME_GET_MICROSEC(t)
Definition: instr_time.h:202
Command ** commands
Definition: pgbench.c:454
static bool set_random_seed(const char *seed)
Definition: pgbench.c:4673
static QueryMode querymode
Definition: pgbench.c:435
void pg_free(void *ptr)
Definition: fe_memutils.c:105
int64 latency_limit
Definition: pgbench.c:150
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:153
pthread_t thread
Definition: pgbench.c:389