PageRenderTime 84ms CodeModel.GetById 39ms RepoModel.GetById 1ms app.codeStats 1ms

/src/bin/pgbench/pgbench.c

https://bitbucket.org/adunstan/pgdevel
C | 6094 lines | 4299 code | 787 blank | 1008 comment | 1030 complexity | 582d1a68b5374ea7045beecb09405bd8 MD5 | raw file
Possible License(s): AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * pgbench.c
  3. *
  4. * A simple benchmark program for PostgreSQL
  5. * Originally written by Tatsuo Ishii and enhanced by many contributors.
  6. *
  7. * src/bin/pgbench/pgbench.c
  8. * Copyright (c) 2000-2018, PostgreSQL Global Development Group
  9. * ALL RIGHTS RESERVED;
  10. *
  11. * Permission to use, copy, modify, and distribute this software and its
  12. * documentation for any purpose, without fee, and without a written agreement
  13. * is hereby granted, provided that the above copyright notice and this
  14. * paragraph and the following two paragraphs appear in all copies.
  15. *
  16. * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
  17. * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
  18. * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
  19. * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
  20. * POSSIBILITY OF SUCH DAMAGE.
  21. *
  22. * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  23. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  24. * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
  25. * ON AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAS NO OBLIGATIONS TO
  26. * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  27. *
  28. */
  29. #ifdef WIN32
  30. #define FD_SETSIZE 1024 /* set before winsock2.h is included */
  31. #endif /* ! WIN32 */
  32. #include "postgres_fe.h"
  33. #include "fe_utils/conditional.h"
  34. #include "getopt_long.h"
  35. #include "libpq-fe.h"
  36. #include "portability/instr_time.h"
  37. #include <ctype.h>
  38. #include <float.h>
  39. #include <limits.h>
  40. #include <math.h>
  41. #include <signal.h>
  42. #include <time.h>
  43. #include <sys/time.h>
  44. #ifdef HAVE_SYS_SELECT_H
  45. #include <sys/select.h>
  46. #endif
  47. #ifdef HAVE_SYS_RESOURCE_H
  48. #include <sys/resource.h> /* for getrlimit */
  49. #endif
  50. #ifndef M_PI
  51. #define M_PI 3.14159265358979323846
  52. #endif
  53. #include "pgbench.h"
  54. #define ERRCODE_UNDEFINED_TABLE "42P01"
  55. /*
  56. * Hashing constants
  57. */
  58. #define FNV_PRIME UINT64CONST(0x100000001b3)
  59. #define FNV_OFFSET_BASIS UINT64CONST(0xcbf29ce484222325)
  60. #define MM2_MUL UINT64CONST(0xc6a4a7935bd1e995)
  61. #define MM2_MUL_TIMES_8 UINT64CONST(0x35253c9ade8f4ca8)
  62. #define MM2_ROT 47
  63. /*
  64. * Multi-platform pthread implementations
  65. */
  66. #ifdef WIN32
  67. /* Use native win32 threads on Windows */
  68. typedef struct win32_pthread *pthread_t;
  69. typedef int pthread_attr_t;
  70. static int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
  71. static int pthread_join(pthread_t th, void **thread_return);
  72. #elif defined(ENABLE_THREAD_SAFETY)
  73. /* Use platform-dependent pthread capability */
  74. #include <pthread.h>
  75. #else
  76. /* No threads implementation, use none (-j 1) */
  77. #define pthread_t void *
  78. #endif
  79. /********************************************************************
  80. * some configurable parameters */
  81. /* max number of clients allowed */
  82. #ifdef FD_SETSIZE
  83. #define MAXCLIENTS (FD_SETSIZE - 10)
  84. #else
  85. #define MAXCLIENTS 1024
  86. #endif
  87. #define DEFAULT_INIT_STEPS "dtgvp" /* default -I setting */
  88. #define LOG_STEP_SECONDS 5 /* seconds between log messages */
  89. #define DEFAULT_NXACTS 10 /* default nxacts */
  90. #define ZIPF_CACHE_SIZE 15 /* cache cells number */
  91. #define MIN_GAUSSIAN_PARAM 2.0 /* minimum parameter for gauss */
  92. #define MAX_ZIPFIAN_PARAM 1000 /* maximum parameter for zipfian */
  93. int nxacts = 0; /* number of transactions per client */
  94. int duration = 0; /* duration in seconds */
  95. int64 end_time = 0; /* when to stop in micro seconds, under -T */
  96. /*
  97. * scaling factor. for example, scale = 10 will make 1000000 tuples in
  98. * pgbench_accounts table.
  99. */
  100. int scale = 1;
  101. /*
  102. * fillfactor. for example, fillfactor = 90 will use only 90 percent
  103. * space during inserts and leave 10 percent free.
  104. */
  105. int fillfactor = 100;
  106. /*
  107. * use unlogged tables?
  108. */
  109. bool unlogged_tables = false;
  110. /*
  111. * log sampling rate (1.0 = log everything, 0.0 = option not given)
  112. */
  113. double sample_rate = 0.0;
  114. /*
  115. * When threads are throttled to a given rate limit, this is the target delay
  116. * to reach that rate in usec. 0 is the default and means no throttling.
  117. */
  118. int64 throttle_delay = 0;
  119. /*
  120. * Transactions which take longer than this limit (in usec) are counted as
  121. * late, and reported as such, although they are completed anyway. When
  122. * throttling is enabled, execution time slots that are more than this late
  123. * are skipped altogether, and counted separately.
  124. */
  125. int64 latency_limit = 0;
  126. /*
  127. * tablespace selection
  128. */
  129. char *tablespace = NULL;
  130. char *index_tablespace = NULL;
  131. /* random seed used when calling srandom() */
  132. int64 random_seed = -1;
  133. /*
  134. * end of configurable parameters
  135. *********************************************************************/
  136. #define nbranches 1 /* Makes little sense to change this. Change
  137. * -s instead */
  138. #define ntellers 10
  139. #define naccounts 100000
  140. /*
  141. * The scale factor at/beyond which 32bit integers are incapable of storing
  142. * 64bit values.
  143. *
  144. * Although the actual threshold is 21474, we use 20000 because it is easier to
  145. * document and remember, and isn't that far away from the real threshold.
  146. */
  147. #define SCALE_32BIT_THRESHOLD 20000
  148. bool use_log; /* log transaction latencies to a file */
  149. bool use_quiet; /* quiet logging onto stderr */
  150. int agg_interval; /* log aggregates instead of individual
  151. * transactions */
  152. bool per_script_stats = false; /* whether to collect stats per script */
  153. int progress = 0; /* thread progress report every this seconds */
  154. bool progress_timestamp = false; /* progress report with Unix time */
  155. int nclients = 1; /* number of clients */
  156. int nthreads = 1; /* number of threads */
  157. bool is_connect; /* establish connection for each transaction */
  158. bool is_latencies; /* report per-command latencies */
  159. int main_pid; /* main process id used in log filename */
  160. char *pghost = "";
  161. char *pgport = "";
  162. char *login = NULL;
  163. char *dbName;
  164. char *logfile_prefix = NULL;
  165. const char *progname;
  166. #define WSEP '@' /* weight separator */
  167. volatile bool timer_exceeded = false; /* flag from signal handler */
  168. /*
  169. * Variable definitions.
  170. *
  171. * If a variable only has a string value, "svalue" is that value, and value is
  172. * "not set". If the value is known, "value" contains the value (in any
  173. * variant).
  174. *
  175. * In this case "svalue" contains the string equivalent of the value, if we've
  176. * had occasion to compute that, or NULL if we haven't.
  177. */
  178. typedef struct
  179. {
  180. char *name; /* variable's name */
  181. char *svalue; /* its value in string form, if known */
  182. PgBenchValue value; /* actual variable's value */
  183. } Variable;
  184. #define MAX_SCRIPTS 128 /* max number of SQL scripts allowed */
  185. #define SHELL_COMMAND_SIZE 256 /* maximum size allowed for shell command */
  186. /*
  187. * Simple data structure to keep stats about something.
  188. *
  189. * XXX probably the first value should be kept and used as an offset for
  190. * better numerical stability...
  191. */
  192. typedef struct SimpleStats
  193. {
  194. int64 count; /* how many values were encountered */
  195. double min; /* the minimum seen */
  196. double max; /* the maximum seen */
  197. double sum; /* sum of values */
  198. double sum2; /* sum of squared values */
  199. } SimpleStats;
  200. /*
  201. * Data structure to hold various statistics: per-thread and per-script stats
  202. * are maintained and merged together.
  203. */
  204. typedef struct StatsData
  205. {
  206. time_t start_time; /* interval start time, for aggregates */
  207. int64 cnt; /* number of transactions, including skipped */
  208. int64 skipped; /* number of transactions skipped under --rate
  209. * and --latency-limit */
  210. SimpleStats latency;
  211. SimpleStats lag;
  212. } StatsData;
  213. /*
  214. * Connection state machine states.
  215. */
  216. typedef enum
  217. {
  218. /*
  219. * The client must first choose a script to execute. Once chosen, it can
  220. * either be throttled (state CSTATE_START_THROTTLE under --rate) or start
  221. * right away (state CSTATE_START_TX).
  222. */
  223. CSTATE_CHOOSE_SCRIPT,
  224. /*
  225. * In CSTATE_START_THROTTLE state, we calculate when to begin the next
  226. * transaction, and advance to CSTATE_THROTTLE. CSTATE_THROTTLE state
  227. * sleeps until that moment. (If throttling is not enabled, doCustom()
  228. * falls directly through from CSTATE_START_THROTTLE to CSTATE_START_TX.)
  229. */
  230. CSTATE_START_THROTTLE,
  231. CSTATE_THROTTLE,
  232. /*
  233. * CSTATE_START_TX performs start-of-transaction processing. Establishes
  234. * a new connection for the transaction, in --connect mode, and records
  235. * the transaction start time.
  236. */
  237. CSTATE_START_TX,
  238. /*
  239. * We loop through these states, to process each command in the script:
  240. *
  241. * CSTATE_START_COMMAND starts the execution of a command. On a SQL
  242. * command, the command is sent to the server, and we move to
  243. * CSTATE_WAIT_RESULT state. On a \sleep meta-command, the timer is set,
  244. * and we enter the CSTATE_SLEEP state to wait for it to expire. Other
  245. * meta-commands are executed immediately.
  246. *
  247. * CSTATE_SKIP_COMMAND for conditional branches which are not executed,
  248. * quickly skip commands that do not need any evaluation.
  249. *
  250. * CSTATE_WAIT_RESULT waits until we get a result set back from the server
  251. * for the current command.
  252. *
  253. * CSTATE_SLEEP waits until the end of \sleep.
  254. *
  255. * CSTATE_END_COMMAND records the end-of-command timestamp, increments the
  256. * command counter, and loops back to CSTATE_START_COMMAND state.
  257. */
  258. CSTATE_START_COMMAND,
  259. CSTATE_SKIP_COMMAND,
  260. CSTATE_WAIT_RESULT,
  261. CSTATE_SLEEP,
  262. CSTATE_END_COMMAND,
  263. /*
  264. * CSTATE_END_TX performs end-of-transaction processing. Calculates
  265. * latency, and logs the transaction. In --connect mode, closes the
  266. * current connection. Chooses the next script to execute and starts over
  267. * in CSTATE_START_THROTTLE state, or enters CSTATE_FINISHED if we have no
  268. * more work to do.
  269. */
  270. CSTATE_END_TX,
  271. /*
  272. * Final states. CSTATE_ABORTED means that the script execution was
  273. * aborted because a command failed, CSTATE_FINISHED means success.
  274. */
  275. CSTATE_ABORTED,
  276. CSTATE_FINISHED
  277. } ConnectionStateEnum;
  278. /*
  279. * Connection state.
  280. */
  281. typedef struct
  282. {
  283. PGconn *con; /* connection handle to DB */
  284. int id; /* client No. */
  285. ConnectionStateEnum state; /* state machine's current state. */
  286. ConditionalStack cstack; /* enclosing conditionals state */
  287. int use_file; /* index in sql_script for this client */
  288. int command; /* command number in script */
  289. /* client variables */
  290. Variable *variables; /* array of variable definitions */
  291. int nvariables; /* number of variables */
  292. bool vars_sorted; /* are variables sorted by name? */
  293. /* various times about current transaction */
  294. int64 txn_scheduled; /* scheduled start time of transaction (usec) */
  295. int64 sleep_until; /* scheduled start time of next cmd (usec) */
  296. instr_time txn_begin; /* used for measuring schedule lag times */
  297. instr_time stmt_begin; /* used for measuring statement latencies */
  298. bool prepared[MAX_SCRIPTS]; /* whether client prepared the script */
  299. /* per client collected stats */
  300. int64 cnt; /* client transaction count, for -t */
  301. int ecnt; /* error count */
  302. } CState;
  303. /*
  304. * Cache cell for zipfian_random call
  305. */
  306. typedef struct
  307. {
  308. /* cell keys */
  309. double s; /* s - parameter of zipfan_random function */
  310. int64 n; /* number of elements in range (max - min + 1) */
  311. double harmonicn; /* generalizedHarmonicNumber(n, s) */
  312. double alpha;
  313. double beta;
  314. double eta;
  315. uint64 last_used; /* last used logical time */
  316. } ZipfCell;
  317. /*
  318. * Zipf cache for zeta values
  319. */
  320. typedef struct
  321. {
  322. uint64 current; /* counter for LRU cache replacement algorithm */
  323. int nb_cells; /* number of filled cells */
  324. int overflowCount; /* number of cache overflows */
  325. ZipfCell cells[ZIPF_CACHE_SIZE];
  326. } ZipfCache;
  327. /*
  328. * Thread state
  329. */
  330. typedef struct
  331. {
  332. int tid; /* thread id */
  333. pthread_t thread; /* thread handle */
  334. CState *state; /* array of CState */
  335. int nstate; /* length of state[] */
  336. unsigned short random_state[3]; /* separate randomness for each thread */
  337. int64 throttle_trigger; /* previous/next throttling (us) */
  338. FILE *logfile; /* where to log, or NULL */
  339. ZipfCache zipf_cache; /* for thread-safe zipfian random number
  340. * generation */
  341. /* per thread collected stats */
  342. instr_time start_time; /* thread start time */
  343. instr_time conn_time;
  344. StatsData stats;
  345. int64 latency_late; /* executed but late transactions */
  346. } TState;
  347. #define INVALID_THREAD ((pthread_t) 0)
  348. /*
  349. * queries read from files
  350. */
  351. #define SQL_COMMAND 1
  352. #define META_COMMAND 2
  353. #define MAX_ARGS 10
  354. typedef enum MetaCommand
  355. {
  356. META_NONE, /* not a known meta-command */
  357. META_SET, /* \set */
  358. META_SETSHELL, /* \setshell */
  359. META_SHELL, /* \shell */
  360. META_SLEEP, /* \sleep */
  361. META_IF, /* \if */
  362. META_ELIF, /* \elif */
  363. META_ELSE, /* \else */
  364. META_ENDIF /* \endif */
  365. } MetaCommand;
  366. typedef enum QueryMode
  367. {
  368. QUERY_SIMPLE, /* simple query */
  369. QUERY_EXTENDED, /* extended query */
  370. QUERY_PREPARED, /* extended query with prepared statements */
  371. NUM_QUERYMODE
  372. } QueryMode;
  373. static QueryMode querymode = QUERY_SIMPLE;
  374. static const char *QUERYMODE[] = {"simple", "extended", "prepared"};
  375. typedef struct
  376. {
  377. char *line; /* text of command line */
  378. int command_num; /* unique index of this Command struct */
  379. int type; /* command type (SQL_COMMAND or META_COMMAND) */
  380. MetaCommand meta; /* meta command identifier, or META_NONE */
  381. int argc; /* number of command words */
  382. char *argv[MAX_ARGS]; /* command word list */
  383. PgBenchExpr *expr; /* parsed expression, if needed */
  384. SimpleStats stats; /* time spent in this command */
  385. } Command;
  386. typedef struct ParsedScript
  387. {
  388. const char *desc; /* script descriptor (eg, file name) */
  389. int weight; /* selection weight */
  390. Command **commands; /* NULL-terminated array of Commands */
  391. StatsData stats; /* total time spent in script */
  392. } ParsedScript;
  393. static ParsedScript sql_script[MAX_SCRIPTS]; /* SQL script files */
  394. static int num_scripts; /* number of scripts in sql_script[] */
  395. static int num_commands = 0; /* total number of Command structs */
  396. static int64 total_weight = 0;
  397. static int debug = 0; /* debug flag */
  398. /* Builtin test scripts */
  399. typedef struct BuiltinScript
  400. {
  401. const char *name; /* very short name for -b ... */
  402. const char *desc; /* short description */
  403. const char *script; /* actual pgbench script */
  404. } BuiltinScript;
  405. static const BuiltinScript builtin_script[] =
  406. {
  407. {
  408. "tpcb-like",
  409. "<builtin: TPC-B (sort of)>",
  410. "\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
  411. "\\set bid random(1, " CppAsString2(nbranches) " * :scale)\n"
  412. "\\set tid random(1, " CppAsString2(ntellers) " * :scale)\n"
  413. "\\set delta random(-5000, 5000)\n"
  414. "BEGIN;\n"
  415. "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
  416. "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
  417. "UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\n"
  418. "UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\n"
  419. "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
  420. "END;\n"
  421. },
  422. {
  423. "simple-update",
  424. "<builtin: simple update>",
  425. "\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
  426. "\\set bid random(1, " CppAsString2(nbranches) " * :scale)\n"
  427. "\\set tid random(1, " CppAsString2(ntellers) " * :scale)\n"
  428. "\\set delta random(-5000, 5000)\n"
  429. "BEGIN;\n"
  430. "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
  431. "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
  432. "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
  433. "END;\n"
  434. },
  435. {
  436. "select-only",
  437. "<builtin: select only>",
  438. "\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
  439. "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
  440. }
  441. };
  442. /* Function prototypes */
  443. static void setNullValue(PgBenchValue *pv);
  444. static void setBoolValue(PgBenchValue *pv, bool bval);
  445. static void setIntValue(PgBenchValue *pv, int64 ival);
  446. static void setDoubleValue(PgBenchValue *pv, double dval);
  447. static bool evaluateExpr(TState *, CState *, PgBenchExpr *, PgBenchValue *);
  448. static void doLog(TState *thread, CState *st,
  449. StatsData *agg, bool skipped, double latency, double lag);
  450. static void processXactStats(TState *thread, CState *st, instr_time *now,
  451. bool skipped, StatsData *agg);
  452. static void pgbench_error(const char *fmt,...) pg_attribute_printf(1, 2);
  453. static void addScript(ParsedScript script);
  454. static void *threadRun(void *arg);
  455. static void setalarm(int seconds);
  456. static void finishCon(CState *st);
  457. /* callback functions for our flex lexer */
  458. static const PsqlScanCallbacks pgbench_callbacks = {
  459. NULL, /* don't need get_variable functionality */
  460. pgbench_error
  461. };
  462. static void
  463. usage(void)
  464. {
  465. printf("%s is a benchmarking tool for PostgreSQL.\n\n"
  466. "Usage:\n"
  467. " %s [OPTION]... [DBNAME]\n"
  468. "\nInitialization options:\n"
  469. " -i, --initialize invokes initialization mode\n"
  470. " -I, --init-steps=[dtgvpf]+ (default \"dtgvp\")\n"
  471. " run selected initialization steps\n"
  472. " -F, --fillfactor=NUM set fill factor\n"
  473. " -n, --no-vacuum do not run VACUUM during initialization\n"
  474. " -q, --quiet quiet logging (one message each 5 seconds)\n"
  475. " -s, --scale=NUM scaling factor\n"
  476. " --foreign-keys create foreign key constraints between tables\n"
  477. " --index-tablespace=TABLESPACE\n"
  478. " create indexes in the specified tablespace\n"
  479. " --tablespace=TABLESPACE create tables in the specified tablespace\n"
  480. " --unlogged-tables create tables as unlogged tables\n"
  481. "\nOptions to select what to run:\n"
  482. " -b, --builtin=NAME[@W] add builtin script NAME weighted at W (default: 1)\n"
  483. " (use \"-b list\" to list available scripts)\n"
  484. " -f, --file=FILENAME[@W] add script FILENAME weighted at W (default: 1)\n"
  485. " -N, --skip-some-updates skip updates of pgbench_tellers and pgbench_branches\n"
  486. " (same as \"-b simple-update\")\n"
  487. " -S, --select-only perform SELECT-only transactions\n"
  488. " (same as \"-b select-only\")\n"
  489. "\nBenchmarking options:\n"
  490. " -c, --client=NUM number of concurrent database clients (default: 1)\n"
  491. " -C, --connect establish new connection for each transaction\n"
  492. " -D, --define=VARNAME=VALUE\n"
  493. " define variable for use by custom script\n"
  494. " -j, --jobs=NUM number of threads (default: 1)\n"
  495. " -l, --log write transaction times to log file\n"
  496. " -L, --latency-limit=NUM count transactions lasting more than NUM ms as late\n"
  497. " -M, --protocol=simple|extended|prepared\n"
  498. " protocol for submitting queries (default: simple)\n"
  499. " -n, --no-vacuum do not run VACUUM before tests\n"
  500. " -P, --progress=NUM show thread progress report every NUM seconds\n"
  501. " -r, --report-latencies report average latency per command\n"
  502. " -R, --rate=NUM target rate in transactions per second\n"
  503. " -s, --scale=NUM report this scale factor in output\n"
  504. " -t, --transactions=NUM number of transactions each client runs (default: 10)\n"
  505. " -T, --time=NUM duration of benchmark test in seconds\n"
  506. " -v, --vacuum-all vacuum all four standard tables before tests\n"
  507. " --aggregate-interval=NUM aggregate data over NUM seconds\n"
  508. " --log-prefix=PREFIX prefix for transaction time log file\n"
  509. " (default: \"pgbench_log\")\n"
  510. " --progress-timestamp use Unix epoch timestamps for progress\n"
  511. " --random-seed=SEED set random seed (\"time\", \"rand\", integer)\n"
  512. " --sampling-rate=NUM fraction of transactions to log (e.g., 0.01 for 1%%)\n"
  513. "\nCommon options:\n"
  514. " -d, --debug print debugging output\n"
  515. " -h, --host=HOSTNAME database server host or socket directory\n"
  516. " -p, --port=PORT database server port number\n"
  517. " -U, --username=USERNAME connect as specified database user\n"
  518. " -V, --version output version information, then exit\n"
  519. " -?, --help show this help, then exit\n"
  520. "\n"
  521. "Report bugs to <pgsql-bugs@postgresql.org>.\n",
  522. progname, progname);
  523. }
  524. /* return whether str matches "^\s*[-+]?[0-9]+$" */
  525. static bool
  526. is_an_int(const char *str)
  527. {
  528. const char *ptr = str;
  529. /* skip leading spaces; cast is consistent with strtoint64 */
  530. while (*ptr && isspace((unsigned char) *ptr))
  531. ptr++;
  532. /* skip sign */
  533. if (*ptr == '+' || *ptr == '-')
  534. ptr++;
  535. /* at least one digit */
  536. if (*ptr && !isdigit((unsigned char) *ptr))
  537. return false;
  538. /* eat all digits */
  539. while (*ptr && isdigit((unsigned char) *ptr))
  540. ptr++;
  541. /* must have reached end of string */
  542. return *ptr == '\0';
  543. }
  544. /*
  545. * strtoint64 -- convert a string to 64-bit integer
  546. *
  547. * This function is a modified version of scanint8() from
  548. * src/backend/utils/adt/int8.c.
  549. */
  550. int64
  551. strtoint64(const char *str)
  552. {
  553. const char *ptr = str;
  554. int64 result = 0;
  555. int sign = 1;
  556. /*
  557. * Do our own scan, rather than relying on sscanf which might be broken
  558. * for long long.
  559. */
  560. /* skip leading spaces */
  561. while (*ptr && isspace((unsigned char) *ptr))
  562. ptr++;
  563. /* handle sign */
  564. if (*ptr == '-')
  565. {
  566. ptr++;
  567. /*
  568. * Do an explicit check for INT64_MIN. Ugly though this is, it's
  569. * cleaner than trying to get the loop below to handle it portably.
  570. */
  571. if (strncmp(ptr, "9223372036854775808", 19) == 0)
  572. {
  573. result = PG_INT64_MIN;
  574. ptr += 19;
  575. goto gotdigits;
  576. }
  577. sign = -1;
  578. }
  579. else if (*ptr == '+')
  580. ptr++;
  581. /* require at least one digit */
  582. if (!isdigit((unsigned char) *ptr))
  583. fprintf(stderr, "invalid input syntax for integer: \"%s\"\n", str);
  584. /* process digits */
  585. while (*ptr && isdigit((unsigned char) *ptr))
  586. {
  587. int64 tmp = result * 10 + (*ptr++ - '0');
  588. if ((tmp / 10) != result) /* overflow? */
  589. fprintf(stderr, "value \"%s\" is out of range for type bigint\n", str);
  590. result = tmp;
  591. }
  592. gotdigits:
  593. /* allow trailing whitespace, but not other trailing chars */
  594. while (*ptr != '\0' && isspace((unsigned char) *ptr))
  595. ptr++;
  596. if (*ptr != '\0')
  597. fprintf(stderr, "invalid input syntax for integer: \"%s\"\n", str);
  598. return ((sign < 0) ? -result : result);
  599. }
  600. /* random number generator: uniform distribution from min to max inclusive */
  601. static int64
  602. getrand(TState *thread, int64 min, int64 max)
  603. {
  604. /*
  605. * Odd coding is so that min and max have approximately the same chance of
  606. * being selected as do numbers between them.
  607. *
  608. * pg_erand48() is thread-safe and concurrent, which is why we use it
  609. * rather than random(), which in glibc is non-reentrant, and therefore
  610. * protected by a mutex, and therefore a bottleneck on machines with many
  611. * CPUs.
  612. */
  613. return min + (int64) ((max - min + 1) * pg_erand48(thread->random_state));
  614. }
  615. /*
  616. * random number generator: exponential distribution from min to max inclusive.
  617. * the parameter is so that the density of probability for the last cut-off max
  618. * value is exp(-parameter).
  619. */
  620. static int64
  621. getExponentialRand(TState *thread, int64 min, int64 max, double parameter)
  622. {
  623. double cut,
  624. uniform,
  625. rand;
  626. /* abort if wrong parameter, but must really be checked beforehand */
  627. Assert(parameter > 0.0);
  628. cut = exp(-parameter);
  629. /* erand in [0, 1), uniform in (0, 1] */
  630. uniform = 1.0 - pg_erand48(thread->random_state);
  631. /*
  632. * inner expression in (cut, 1] (if parameter > 0), rand in [0, 1)
  633. */
  634. Assert((1.0 - cut) != 0.0);
  635. rand = -log(cut + (1.0 - cut) * uniform) / parameter;
  636. /* return int64 random number within between min and max */
  637. return min + (int64) ((max - min + 1) * rand);
  638. }
  639. /* random number generator: gaussian distribution from min to max inclusive */
  640. static int64
  641. getGaussianRand(TState *thread, int64 min, int64 max, double parameter)
  642. {
  643. double stdev;
  644. double rand;
  645. /* abort if parameter is too low, but must really be checked beforehand */
  646. Assert(parameter >= MIN_GAUSSIAN_PARAM);
  647. /*
  648. * Get user specified random number from this loop, with -parameter <
  649. * stdev <= parameter
  650. *
  651. * This loop is executed until the number is in the expected range.
  652. *
  653. * As the minimum parameter is 2.0, the probability of looping is low:
  654. * sqrt(-2 ln(r)) <= 2 => r >= e^{-2} ~ 0.135, then when taking the
  655. * average sinus multiplier as 2/pi, we have a 8.6% looping probability in
  656. * the worst case. For a parameter value of 5.0, the looping probability
  657. * is about e^{-5} * 2 / pi ~ 0.43%.
  658. */
  659. do
  660. {
  661. /*
  662. * pg_erand48 generates [0,1), but for the basic version of the
  663. * Box-Muller transform the two uniformly distributed random numbers
  664. * are expected in (0, 1] (see
  665. * http://en.wikipedia.org/wiki/Box_muller)
  666. */
  667. double rand1 = 1.0 - pg_erand48(thread->random_state);
  668. double rand2 = 1.0 - pg_erand48(thread->random_state);
  669. /* Box-Muller basic form transform */
  670. double var_sqrt = sqrt(-2.0 * log(rand1));
  671. stdev = var_sqrt * sin(2.0 * M_PI * rand2);
  672. /*
  673. * we may try with cos, but there may be a bias induced if the
  674. * previous value fails the test. To be on the safe side, let us try
  675. * over.
  676. */
  677. }
  678. while (stdev < -parameter || stdev >= parameter);
  679. /* stdev is in [-parameter, parameter), normalization to [0,1) */
  680. rand = (stdev + parameter) / (parameter * 2.0);
  681. /* return int64 random number within between min and max */
  682. return min + (int64) ((max - min + 1) * rand);
  683. }
  684. /*
  685. * random number generator: generate a value, such that the series of values
  686. * will approximate a Poisson distribution centered on the given value.
  687. */
  688. static int64
  689. getPoissonRand(TState *thread, int64 center)
  690. {
  691. /*
  692. * Use inverse transform sampling to generate a value > 0, such that the
  693. * expected (i.e. average) value is the given argument.
  694. */
  695. double uniform;
  696. /* erand in [0, 1), uniform in (0, 1] */
  697. uniform = 1.0 - pg_erand48(thread->random_state);
  698. return (int64) (-log(uniform) * ((double) center) + 0.5);
  699. }
  700. /* helper function for getZipfianRand */
  701. static double
  702. generalizedHarmonicNumber(int64 n, double s)
  703. {
  704. int i;
  705. double ans = 0.0;
  706. for (i = n; i > 1; i--)
  707. ans += pow(i, -s);
  708. return ans + 1.0;
  709. }
  710. /* set harmonicn and other parameters to cache cell */
  711. static void
  712. zipfSetCacheCell(ZipfCell *cell, int64 n, double s)
  713. {
  714. double harmonic2;
  715. cell->n = n;
  716. cell->s = s;
  717. harmonic2 = generalizedHarmonicNumber(2, s);
  718. cell->harmonicn = generalizedHarmonicNumber(n, s);
  719. cell->alpha = 1.0 / (1.0 - s);
  720. cell->beta = pow(0.5, s);
  721. cell->eta = (1.0 - pow(2.0 / n, 1.0 - s)) / (1.0 - harmonic2 / cell->harmonicn);
  722. }
  723. /*
  724. * search for cache cell with keys (n, s)
  725. * and create new cell if it does not exist
  726. */
  727. static ZipfCell *
  728. zipfFindOrCreateCacheCell(ZipfCache *cache, int64 n, double s)
  729. {
  730. int i,
  731. least_recently_used = 0;
  732. ZipfCell *cell;
  733. /* search cached cell for given parameters */
  734. for (i = 0; i < cache->nb_cells; i++)
  735. {
  736. cell = &cache->cells[i];
  737. if (cell->n == n && cell->s == s)
  738. return &cache->cells[i];
  739. if (cell->last_used < cache->cells[least_recently_used].last_used)
  740. least_recently_used = i;
  741. }
  742. /* create new one if it does not exist */
  743. if (cache->nb_cells < ZIPF_CACHE_SIZE)
  744. i = cache->nb_cells++;
  745. else
  746. {
  747. /* replace LRU cell if cache is full */
  748. i = least_recently_used;
  749. cache->overflowCount++;
  750. }
  751. zipfSetCacheCell(&cache->cells[i], n, s);
  752. cache->cells[i].last_used = cache->current++;
  753. return &cache->cells[i];
  754. }
  755. /*
  756. * Computing zipfian using rejection method, based on
  757. * "Non-Uniform Random Variate Generation",
  758. * Luc Devroye, p. 550-551, Springer 1986.
  759. */
  760. static int64
  761. computeIterativeZipfian(TState *thread, int64 n, double s)
  762. {
  763. double b = pow(2.0, s - 1.0);
  764. double x,
  765. t,
  766. u,
  767. v;
  768. while (true)
  769. {
  770. /* random variates */
  771. u = pg_erand48(thread->random_state);
  772. v = pg_erand48(thread->random_state);
  773. x = floor(pow(u, -1.0 / (s - 1.0)));
  774. t = pow(1.0 + 1.0 / x, s - 1.0);
  775. /* reject if too large or out of bound */
  776. if (v * x * (t - 1.0) / (b - 1.0) <= t / b && x <= n)
  777. break;
  778. }
  779. return (int64) x;
  780. }
  781. /*
  782. * Computing zipfian using harmonic numbers, based on algorithm described in
  783. * "Quickly Generating Billion-Record Synthetic Databases",
  784. * Jim Gray et al, SIGMOD 1994
  785. */
  786. static int64
  787. computeHarmonicZipfian(TState *thread, int64 n, double s)
  788. {
  789. ZipfCell *cell = zipfFindOrCreateCacheCell(&thread->zipf_cache, n, s);
  790. double uniform = pg_erand48(thread->random_state);
  791. double uz = uniform * cell->harmonicn;
  792. if (uz < 1.0)
  793. return 1;
  794. if (uz < 1.0 + cell->beta)
  795. return 2;
  796. return 1 + (int64) (cell->n * pow(cell->eta * uniform - cell->eta + 1.0, cell->alpha));
  797. }
  798. /* random number generator: zipfian distribution from min to max inclusive */
  799. static int64
  800. getZipfianRand(TState *thread, int64 min, int64 max, double s)
  801. {
  802. int64 n = max - min + 1;
  803. /* abort if parameter is invalid */
  804. Assert(s > 0.0 && s != 1.0 && s <= MAX_ZIPFIAN_PARAM);
  805. return min - 1 + ((s > 1)
  806. ? computeIterativeZipfian(thread, n, s)
  807. : computeHarmonicZipfian(thread, n, s));
  808. }
  809. /*
  810. * FNV-1a hash function
  811. */
  812. static int64
  813. getHashFnv1a(int64 val, uint64 seed)
  814. {
  815. int64 result;
  816. int i;
  817. result = FNV_OFFSET_BASIS ^ seed;
  818. for (i = 0; i < 8; ++i)
  819. {
  820. int32 octet = val & 0xff;
  821. val = val >> 8;
  822. result = result ^ octet;
  823. result = result * FNV_PRIME;
  824. }
  825. return result;
  826. }
  827. /*
  828. * Murmur2 hash function
  829. *
  830. * Based on original work of Austin Appleby
  831. * https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp
  832. */
  833. static int64
  834. getHashMurmur2(int64 val, uint64 seed)
  835. {
  836. uint64 result = seed ^ MM2_MUL_TIMES_8; /* sizeof(int64) */
  837. uint64 k = (uint64) val;
  838. k *= MM2_MUL;
  839. k ^= k >> MM2_ROT;
  840. k *= MM2_MUL;
  841. result ^= k;
  842. result *= MM2_MUL;
  843. result ^= result >> MM2_ROT;
  844. result *= MM2_MUL;
  845. result ^= result >> MM2_ROT;
  846. return (int64) result;
  847. }
  848. /*
  849. * Initialize the given SimpleStats struct to all zeroes
  850. */
  851. static void
  852. initSimpleStats(SimpleStats *ss)
  853. {
  854. memset(ss, 0, sizeof(SimpleStats));
  855. }
  856. /*
  857. * Accumulate one value into a SimpleStats struct.
  858. */
  859. static void
  860. addToSimpleStats(SimpleStats *ss, double val)
  861. {
  862. if (ss->count == 0 || val < ss->min)
  863. ss->min = val;
  864. if (ss->count == 0 || val > ss->max)
  865. ss->max = val;
  866. ss->count++;
  867. ss->sum += val;
  868. ss->sum2 += val * val;
  869. }
  870. /*
  871. * Merge two SimpleStats objects
  872. */
  873. static void
  874. mergeSimpleStats(SimpleStats *acc, SimpleStats *ss)
  875. {
  876. if (acc->count == 0 || ss->min < acc->min)
  877. acc->min = ss->min;
  878. if (acc->count == 0 || ss->max > acc->max)
  879. acc->max = ss->max;
  880. acc->count += ss->count;
  881. acc->sum += ss->sum;
  882. acc->sum2 += ss->sum2;
  883. }
  884. /*
  885. * Initialize a StatsData struct to mostly zeroes, with its start time set to
  886. * the given value.
  887. */
  888. static void
  889. initStats(StatsData *sd, time_t start_time)
  890. {
  891. sd->start_time = start_time;
  892. sd->cnt = 0;
  893. sd->skipped = 0;
  894. initSimpleStats(&sd->latency);
  895. initSimpleStats(&sd->lag);
  896. }
  897. /*
  898. * Accumulate one additional item into the given stats object.
  899. */
  900. static void
  901. accumStats(StatsData *stats, bool skipped, double lat, double lag)
  902. {
  903. stats->cnt++;
  904. if (skipped)
  905. {
  906. /* no latency to record on skipped transactions */
  907. stats->skipped++;
  908. }
  909. else
  910. {
  911. addToSimpleStats(&stats->latency, lat);
  912. /* and possibly the same for schedule lag */
  913. if (throttle_delay)
  914. addToSimpleStats(&stats->lag, lag);
  915. }
  916. }
  917. /* call PQexec() and exit() on failure */
  918. static void
  919. executeStatement(PGconn *con, const char *sql)
  920. {
  921. PGresult *res;
  922. res = PQexec(con, sql);
  923. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  924. {
  925. fprintf(stderr, "%s", PQerrorMessage(con));
  926. exit(1);
  927. }
  928. PQclear(res);
  929. }
  930. /* call PQexec() and complain, but without exiting, on failure */
  931. static void
  932. tryExecuteStatement(PGconn *con, const char *sql)
  933. {
  934. PGresult *res;
  935. res = PQexec(con, sql);
  936. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  937. {
  938. fprintf(stderr, "%s", PQerrorMessage(con));
  939. fprintf(stderr, "(ignoring this error and continuing anyway)\n");
  940. }
  941. PQclear(res);
  942. }
  943. /* set up a connection to the backend */
  944. static PGconn *
  945. doConnect(void)
  946. {
  947. PGconn *conn;
  948. bool new_pass;
  949. static bool have_password = false;
  950. static char password[100];
  951. /*
  952. * Start the connection. Loop until we have a password if requested by
  953. * backend.
  954. */
  955. do
  956. {
  957. #define PARAMS_ARRAY_SIZE 7
  958. const char *keywords[PARAMS_ARRAY_SIZE];
  959. const char *values[PARAMS_ARRAY_SIZE];
  960. keywords[0] = "host";
  961. values[0] = pghost;
  962. keywords[1] = "port";
  963. values[1] = pgport;
  964. keywords[2] = "user";
  965. values[2] = login;
  966. keywords[3] = "password";
  967. values[3] = have_password ? password : NULL;
  968. keywords[4] = "dbname";
  969. values[4] = dbName;
  970. keywords[5] = "fallback_application_name";
  971. values[5] = progname;
  972. keywords[6] = NULL;
  973. values[6] = NULL;
  974. new_pass = false;
  975. conn = PQconnectdbParams(keywords, values, true);
  976. if (!conn)
  977. {
  978. fprintf(stderr, "connection to database \"%s\" failed\n",
  979. dbName);
  980. return NULL;
  981. }
  982. if (PQstatus(conn) == CONNECTION_BAD &&
  983. PQconnectionNeedsPassword(conn) &&
  984. !have_password)
  985. {
  986. PQfinish(conn);
  987. simple_prompt("Password: ", password, sizeof(password), false);
  988. have_password = true;
  989. new_pass = true;
  990. }
  991. } while (new_pass);
  992. /* check to see that the backend connection was successfully made */
  993. if (PQstatus(conn) == CONNECTION_BAD)
  994. {
  995. fprintf(stderr, "connection to database \"%s\" failed:\n%s",
  996. dbName, PQerrorMessage(conn));
  997. PQfinish(conn);
  998. return NULL;
  999. }
  1000. return conn;
  1001. }
  1002. /* throw away response from backend */
  1003. static void
  1004. discard_response(CState *state)
  1005. {
  1006. PGresult *res;
  1007. do
  1008. {
  1009. res = PQgetResult(state->con);
  1010. if (res)
  1011. PQclear(res);
  1012. } while (res);
  1013. }
  1014. /* qsort comparator for Variable array */
  1015. static int
  1016. compareVariableNames(const void *v1, const void *v2)
  1017. {
  1018. return strcmp(((const Variable *) v1)->name,
  1019. ((const Variable *) v2)->name);
  1020. }
  1021. /* Locate a variable by name; returns NULL if unknown */
  1022. static Variable *
  1023. lookupVariable(CState *st, char *name)
  1024. {
  1025. Variable key;
  1026. /* On some versions of Solaris, bsearch of zero items dumps core */
  1027. if (st->nvariables <= 0)
  1028. return NULL;
  1029. /* Sort if we have to */
  1030. if (!st->vars_sorted)
  1031. {
  1032. qsort((void *) st->variables, st->nvariables, sizeof(Variable),
  1033. compareVariableNames);
  1034. st->vars_sorted = true;
  1035. }
  1036. /* Now we can search */
  1037. key.name = name;
  1038. return (Variable *) bsearch((void *) &key,
  1039. (void *) st->variables,
  1040. st->nvariables,
  1041. sizeof(Variable),
  1042. compareVariableNames);
  1043. }
  1044. /* Get the value of a variable, in string form; returns NULL if unknown */
  1045. static char *
  1046. getVariable(CState *st, char *name)
  1047. {
  1048. Variable *var;
  1049. char stringform[64];
  1050. var = lookupVariable(st, name);
  1051. if (var == NULL)
  1052. return NULL; /* not found */
  1053. if (var->svalue)
  1054. return var->svalue; /* we have it in string form */
  1055. /* We need to produce a string equivalent of the value */
  1056. Assert(var->value.type != PGBT_NO_VALUE);
  1057. if (var->value.type == PGBT_NULL)
  1058. snprintf(stringform, sizeof(stringform), "NULL");
  1059. else if (var->value.type == PGBT_BOOLEAN)
  1060. snprintf(stringform, sizeof(stringform),
  1061. "%s", var->value.u.bval ? "true" : "false");
  1062. else if (var->value.type == PGBT_INT)
  1063. snprintf(stringform, sizeof(stringform),
  1064. INT64_FORMAT, var->value.u.ival);
  1065. else if (var->value.type == PGBT_DOUBLE)
  1066. snprintf(stringform, sizeof(stringform),
  1067. "%.*g", DBL_DIG, var->value.u.dval);
  1068. else /* internal error, unexpected type */
  1069. Assert(0);
  1070. var->svalue = pg_strdup(stringform);
  1071. return var->svalue;
  1072. }
  1073. /* Try to convert variable to a value; return false on failure */
  1074. static bool
  1075. makeVariableValue(Variable *var)
  1076. {
  1077. size_t slen;
  1078. if (var->value.type != PGBT_NO_VALUE)
  1079. return true; /* no work */
  1080. slen = strlen(var->svalue);
  1081. if (slen == 0)
  1082. /* what should it do on ""? */
  1083. return false;
  1084. if (pg_strcasecmp(var->svalue, "null") == 0)
  1085. {
  1086. setNullValue(&var->value);
  1087. }
  1088. /*
  1089. * accept prefixes such as y, ye, n, no... but not for "o". 0/1 are
  1090. * recognized later as an int, which is converted to bool if needed.
  1091. */
  1092. else if (pg_strncasecmp(var->svalue, "true", slen) == 0 ||
  1093. pg_strncasecmp(var->svalue, "yes", slen) == 0 ||
  1094. pg_strcasecmp(var->svalue, "on") == 0)
  1095. {
  1096. setBoolValue(&var->value, true);
  1097. }
  1098. else if (pg_strncasecmp(var->svalue, "false", slen) == 0 ||
  1099. pg_strncasecmp(var->svalue, "no", slen) == 0 ||
  1100. pg_strcasecmp(var->svalue, "off") == 0 ||
  1101. pg_strcasecmp(var->svalue, "of") == 0)
  1102. {
  1103. setBoolValue(&var->value, false);
  1104. }
  1105. else if (is_an_int(var->svalue))
  1106. {
  1107. setIntValue(&var->value, strtoint64(var->svalue));
  1108. }
  1109. else /* type should be double */
  1110. {
  1111. double dv;
  1112. char xs;
  1113. if (sscanf(var->svalue, "%lf%c", &dv, &xs) != 1)
  1114. {
  1115. fprintf(stderr,
  1116. "malformed variable \"%s\" value: \"%s\"\n",
  1117. var->name, var->svalue);
  1118. return false;
  1119. }
  1120. setDoubleValue(&var->value, dv);
  1121. }
  1122. return true;
  1123. }
  1124. /*
  1125. * Check whether a variable's name is allowed.
  1126. *
  1127. * We allow any non-ASCII character, as well as ASCII letters, digits, and
  1128. * underscore.
  1129. *
  1130. * Keep this in sync with the definitions of variable name characters in
  1131. * "src/fe_utils/psqlscan.l", "src/bin/psql/psqlscanslash.l" and
  1132. * "src/bin/pgbench/exprscan.l". Also see parseVariable(), below.
  1133. *
  1134. * Note: this static function is copied from "src/bin/psql/variables.c"
  1135. */
  1136. static bool
  1137. valid_variable_name(const char *name)
  1138. {
  1139. const unsigned char *ptr = (const unsigned char *) name;
  1140. /* Mustn't be zero-length */
  1141. if (*ptr == '\0')
  1142. return false;
  1143. while (*ptr)
  1144. {
  1145. if (IS_HIGHBIT_SET(*ptr) ||
  1146. strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
  1147. "_0123456789", *ptr) != NULL)
  1148. ptr++;
  1149. else
  1150. return false;
  1151. }
  1152. return true;
  1153. }
  1154. /*
  1155. * Lookup a variable by name, creating it if need be.
  1156. * Caller is expected to assign a value to the variable.
  1157. * Returns NULL on failure (bad name).
  1158. */
  1159. static Variable *
  1160. lookupCreateVariable(CState *st, const char *context, char *name)
  1161. {
  1162. Variable *var;
  1163. var = lookupVariable(st, name);
  1164. if (var == NULL)
  1165. {
  1166. Variable *newvars;
  1167. /*
  1168. * Check for the name only when declaring a new variable to avoid
  1169. * overhead.
  1170. */
  1171. if (!valid_variable_name(name))
  1172. {
  1173. fprintf(stderr, "%s: invalid variable name: \"%s\"\n",
  1174. context, name);
  1175. return NULL;
  1176. }
  1177. /* Create variable at the end of the array */
  1178. if (st->variables)
  1179. newvars = (Variable *) pg_realloc(st->variables,
  1180. (st->nvariables + 1) * sizeof(Variable));
  1181. else
  1182. newvars = (Variable *) pg_malloc(sizeof(Variable));
  1183. st->variables = newvars;
  1184. var = &newvars[st->nvariables];
  1185. var->name = pg_strdup(name);
  1186. var->svalue = NULL;
  1187. /* caller is expected to initialize remaining fields */
  1188. st->nvariables++;
  1189. /* we don't re-sort the array till we have to */
  1190. st->vars_sorted = false;
  1191. }
  1192. return var;
  1193. }
  1194. /* Assign a string value to a variable, creating it if need be */
  1195. /* Returns false on failure (bad name) */
  1196. static bool
  1197. putVariable(CState *st, const char *context, char *name, const char *value)
  1198. {
  1199. Variable *var;
  1200. char *val;
  1201. var = lookupCreateVariable(st, context, name);
  1202. if (!var)
  1203. return false;
  1204. /* dup then free, in case value is pointing at this variable */
  1205. val = pg_strdup(value);
  1206. if (var->svalue)
  1207. free(var->svalue);
  1208. var->svalue = val;
  1209. var->value.type = PGBT_NO_VALUE;
  1210. return true;
  1211. }
  1212. /* Assign a value to a variable, creating it if need be */
  1213. /* Returns false on failure (bad name) */
  1214. static bool
  1215. putVariableValue(CState *st, const char *context, char *name,
  1216. const PgBenchValue *value)
  1217. {
  1218. Variable *var;
  1219. var = lookupCreateVariable(st, context, name);
  1220. if (!var)
  1221. return false;
  1222. if (var->svalue)
  1223. free(var->svalue);
  1224. var->svalue = NULL;
  1225. var->value = *value;
  1226. return true;
  1227. }
  1228. /* Assign an integer value to a variable, creating it if need be */
  1229. /* Returns false on failure (bad name) */
  1230. static bool
  1231. putVariableInt(CState *st, const char *context, char *name, int64 value)
  1232. {
  1233. PgBenchValue val;
  1234. setIntValue(&val, value);
  1235. return putVariableValue(st, context, name, &val);
  1236. }
  1237. /*
  1238. * Parse a possible variable reference (:varname).
  1239. *
  1240. * "sql" points at a colon. If what follows it looks like a valid
  1241. * variable name, return a malloc'd string containing the variable name,
  1242. * and set *eaten to the number of characters consumed.
  1243. * Otherwise, return NULL.
  1244. */
  1245. static char *
  1246. parseVariable(const char *sql, int *eaten)
  1247. {
  1248. int i = 0;
  1249. char *name;
  1250. do
  1251. {
  1252. i++;
  1253. } while (IS_HIGHBIT_SET(sql[i]) ||
  1254. strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
  1255. "_0123456789", sql[i]) != NULL);
  1256. if (i == 1)
  1257. return NULL; /* no valid variable name chars */
  1258. name = pg_malloc(i);
  1259. memcpy(name, &sql[1], i - 1);
  1260. name[i - 1] = '\0';
  1261. *eaten = i;
  1262. return name;
  1263. }
  1264. static char *
  1265. replaceVariable(char **sql, char *param, int len, char *value)
  1266. {
  1267. int valueln = strlen(value);
  1268. if (valueln > len)
  1269. {
  1270. size_t offset = param - *sql;
  1271. *sql = pg_realloc(*sql, strlen(*sql) - len + valueln + 1);
  1272. param = *sql + offset;
  1273. }
  1274. if (valueln != len)
  1275. memmove(param + valueln, param + len, strlen(param + len) + 1);
  1276. memcpy(param, value, valueln);
  1277. return param + valueln;
  1278. }
  1279. static char *
  1280. assignVariables(CState *st, char *sql)
  1281. {
  1282. char *p,
  1283. *name,
  1284. *val;
  1285. p = sql;
  1286. while ((p = strchr(p, ':')) != NULL)
  1287. {
  1288. int eaten;
  1289. name = parseVariable(p, &eaten);
  1290. if (name == NULL)
  1291. {
  1292. while (*p == ':')
  1293. {
  1294. p++;
  1295. }
  1296. continue;
  1297. }
  1298. val = getVariable(st, name);
  1299. free(name);
  1300. if (val == NULL)
  1301. {
  1302. p++;
  1303. continue;
  1304. }
  1305. p = replaceVariable(&sql, p, eaten, val);
  1306. }
  1307. return sql;
  1308. }
  1309. static void
  1310. getQueryParams(CState *st, const Command *command, const char **params)
  1311. {
  1312. int i;
  1313. for (i = 0; i < command->argc - 1; i++)
  1314. params[i] = getVariable(st, command->argv[i + 1]);
  1315. }
  1316. static char *
  1317. valueTypeName(PgBenchValue *pval)
  1318. {
  1319. if (pval->type == PGBT_NO_VALUE)
  1320. return "none";
  1321. else if (pval->type == PGBT_NULL)
  1322. return "null";
  1323. else if (pval->type == PGBT_INT)
  1324. return "int";
  1325. else if (pval->type == PGBT_DOUBLE)
  1326. return "double";
  1327. else if (pval->type == PGBT_BOOLEAN)
  1328. return "boolean";
  1329. else
  1330. {
  1331. /* internal error, should never get there */
  1332. Assert(false);
  1333. return NULL;
  1334. }
  1335. }
  1336. /* get a value as a boolean, or tell if there is a problem */
  1337. static bool
  1338. coerceToBool(PgBenchValue *pval, bool *bval)
  1339. {
  1340. if (pval->type == PGBT_BOOLEAN)
  1341. {
  1342. *bval = pval->u.bval;
  1343. return true;
  1344. }
  1345. else /* NULL, INT or DOUBLE */
  1346. {
  1347. fprintf(stderr, "cannot coerce %s to boolean\n", valueTypeName(pval));
  1348. *bval = false; /* suppress uninitialized-variable warnings */
  1349. return false;
  1350. }
  1351. }
  1352. /*
  1353. * Return true or false from an expression for conditional purposes.
  1354. * Non zero numerical values are true, zero and NULL are false.
  1355. */
  1356. static bool
  1357. valueTruth(PgBenchValue *pval)
  1358. {
  1359. switch (pval->type)
  1360. {
  1361. case PGBT_NULL:
  1362. return false;
  1363. case PGBT_BOOLEAN:
  1364. return pval->u.bval;
  1365. case PGBT_INT:
  1366. return pval->u.ival != 0;
  1367. case PGBT_DOUBLE:
  1368. return pval->u.dval != 0.0;
  1369. default:
  1370. /* internal error, unexpected type */
  1371. Assert(0);
  1372. return false;
  1373. }
  1374. }
  1375. /* get a value as an int, tell if there is a problem */
  1376. static bool
  1377. coerceToInt(PgBenchValue *pval, int64 *ival)
  1378. {
  1379. if (pval->type == PGBT_INT)
  1380. {
  1381. *ival = pval->u.ival;
  1382. return true;
  1383. }
  1384. else if (pval->type == PGBT_DOUBLE)
  1385. {
  1386. double dval = pval->u.dval;
  1387. if (dval < PG_INT64_MIN || PG_INT64_MAX < dval)
  1388. {
  1389. fprintf(stderr, "double to int overflow for %f\n", dval);
  1390. return false;
  1391. }
  1392. *ival = (int64) dval;
  1393. return true;
  1394. }
  1395. else /* BOOLEAN or NULL */
  1396. {
  1397. fprintf(stderr, "cannot coerce %s to int\n", valueTypeName(pval));
  1398. return false;
  1399. }
  1400. }
  1401. /* get a value as a double, or tell if there is a problem */
  1402. static bool
  1403. coerceToDouble(PgBenchValue *pval, double *dval)
  1404. {
  1405. if (pval->type == PGBT_DOUBLE)
  1406. {
  1407. *dval = pval->u.dval;
  1408. return true;
  1409. }
  1410. else if (pval->type == PGBT_INT)
  1411. {
  1412. *dval = (double) pval->u.ival;
  1413. return true;
  1414. }
  1415. else /* BOOLEAN or NULL */
  1416. {
  1417. fprintf(stderr, "cannot coerce %s to double\n", valueTypeName(pval));
  1418. return false;
  1419. }
  1420. }
  1421. /* assign a null value */
  1422. static void
  1423. setNullValue(PgBenchValue *pv)
  1424. {
  1425. pv->type = PGBT_NULL;
  1426. pv->u.ival = 0;
  1427. }
  1428. /* assign a boolean value */
  1429. static void
  1430. setBoolValue(PgBenchValue *pv, bool bval)
  1431. {
  1432. pv->type = PGBT_BOOLEAN;
  1433. pv->u.bval = bval;
  1434. }
  1435. /* assign an integer value */
  1436. static void
  1437. setIntValue(PgBenchValue *pv, int64 ival)
  1438. {
  1439. pv->type = PGBT_INT;
  1440. pv->u.ival = ival;
  1441. }
  1442. /* assign a double value */
  1443. static void
  1444. setDoubleValue(PgBenchValue *pv, double dval)
  1445. {
  1446. pv->type = PGBT_DOUBLE;
  1447. pv->u.dval = dval;
  1448. }
  1449. static bool
  1450. isLazyFunc(PgBenchFunction func)
  1451. {
  1452. return func == PGBENCH_AND || func == PGBENCH_OR || func == PGBENCH_CASE;
  1453. }
  1454. /* lazy evaluation of some functions */
  1455. static bool
  1456. evalLazyFunc(TState *thread, CState *st,
  1457. PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
  1458. {
  1459. PgBenchValue a1,
  1460. a2;
  1461. bool ba1,
  1462. ba2;
  1463. Assert(isLazyFunc(func) && args != NULL && args->next != NULL);
  1464. /* args points to first condition */
  1465. if (!evaluateExpr(thread, st, args->expr, &a1))
  1466. return false;
  1467. /* second condition for AND/OR and corresponding branch for CASE */
  1468. args = args->next;
  1469. switch (func)
  1470. {
  1471. case PGBENCH_AND:
  1472. if (a1.type == PGBT_NULL)
  1473. {
  1474. setNullValue(retval);
  1475. return true;
  1476. }
  1477. if (!coerceToBool(&a1, &ba1))
  1478. return false;
  1479. if (!ba1)
  1480. {
  1481. setBoolValue(retval, false);
  1482. return true;
  1483. }
  1484. if (!evaluateExpr(thread, st, args->expr, &a2))
  1485. return false;
  1486. if (a2.type == PGBT_NULL)
  1487. {
  1488. setNullValue(retval);
  1489. return true;
  1490. }
  1491. else if (!coerceToBool(&a2, &ba2))
  1492. return false;
  1493. else
  1494. {
  1495. setBoolValue(retval, ba2);
  1496. return true;
  1497. }
  1498. return true;
  1499. case PGBENCH_OR:
  1500. if (a1.type == PGBT_NULL)
  1501. {
  1502. setNullValue(retval);
  1503. return true;
  1504. }
  1505. if (!coerceToBool(&a1, &ba1))
  1506. return false;
  1507. if (ba1)
  1508. {
  1509. setBoolValue(retval, true);
  1510. return true;
  1511. }
  1512. if (!evaluateExpr(thread, st, args->expr, &a2))
  1513. return false;
  1514. if (a2.type == PGBT_NULL)
  1515. {
  1516. setNullValue(retval);
  1517. return true;
  1518. }
  1519. else if (!coerceToBool(&a2, &ba2))
  1520. return false;
  1521. else
  1522. {
  1523. setBoolValue(retval, ba2);
  1524. return true;
  1525. }
  1526. case PGBENCH_CASE:
  1527. /* when true, execute branch */
  1528. if (valueTruth(&a1))
  1529. return evaluateExpr(thread, st, args->expr, retval);
  1530. /* now args contains next condition or final else expression */
  1531. args = args->next;
  1532. /* final else case? */
  1533. if (args->next == NULL)
  1534. return evaluateExpr(thread, st, args->expr, retval);
  1535. /* no, another when, proceed */
  1536. return evalLazyFunc(thread, st, PGBENCH_CASE, args, retval);
  1537. default:
  1538. /* internal error, cannot get here */
  1539. Assert(0);
  1540. break;
  1541. }
  1542. return false;
  1543. }
  1544. /* maximum number of function arguments */
  1545. #define MAX_FARGS 16
  1546. /*
  1547. * Recursive evaluation of standard functions,
  1548. * which do not require lazy evaluation.
  1549. */
  1550. static bool
  1551. evalStandardFunc(TState *thread, CState *st,
  1552. PgBenchFunction func, PgBenchExprLink *args,
  1553. PgBenchValue *retval)
  1554. {
  1555. /* evaluate all function arguments */
  1556. int nargs = 0;
  1557. PgBenchValue vargs[MAX_FARGS];
  1558. PgBenchExprLink *l = args;
  1559. bool has_null = false;
  1560. for (nargs = 0; nargs < MAX_FARGS && l != NULL; nargs++, l = l->next)
  1561. {
  1562. if (!evaluateExpr(thread, st, l->expr, &vargs[nargs]))
  1563. return false;
  1564. has_null |= vargs[nargs].type == PGBT_NULL;
  1565. }
  1566. if (l != NULL)
  1567. {
  1568. fprintf(stderr,
  1569. "too many function arguments, maximum is %d\n", MAX_FARGS);
  1570. return false;
  1571. }
  1572. /* NULL arguments */
  1573. if (has_null && func != PGBENCH_IS && func != PGBENCH_DEBUG)
  1574. {
  1575. setNullValue(retval);
  1576. return true;
  1577. }
  1578. /* then evaluate function */
  1579. switch (func)
  1580. {
  1581. /* overloaded operators */
  1582. case PGBENCH_ADD:
  1583. case PGBENCH_SUB:
  1584. case PGBENCH_MUL:
  1585. case PGBENCH_DIV:
  1586. case PGBENCH_MOD:
  1587. case PGBENCH_EQ:
  1588. case PGBENCH_NE:
  1589. case PGBENCH_LE:
  1590. case PGBENCH_LT:
  1591. {
  1592. PgBenchValue *lval = &vargs[0],
  1593. *rval = &vargs[1];
  1594. Assert(nargs == 2);
  1595. /* overloaded type management, double if some double */
  1596. if ((lval->type == PGBT_DOUBLE ||
  1597. rval->type == PGBT_DOUBLE) && func != PGBENCH_MOD)
  1598. {
  1599. double ld,
  1600. rd;
  1601. if (!coerceToDouble(lval, &ld) ||
  1602. !coerceToDouble(rval, &rd))
  1603. return false;
  1604. switch (func)
  1605. {
  1606. case PGBENCH_ADD:
  1607. setDoubleValue(retval, ld + rd);
  1608. return true;
  1609. case PGBENCH_SUB:
  1610. setDoubleValue(retval, ld - rd);
  1611. return true;
  1612. case PGBENCH_MUL:
  1613. setDoubleValue(retval, ld * rd);
  1614. return true;
  1615. case PGBENCH_DIV:
  1616. setDoubleValue(retval, ld / rd);
  1617. return true;
  1618. case PGBENCH_EQ:
  1619. setBoolValue(retval, ld == rd);
  1620. return true;
  1621. case PGBENCH_NE:
  1622. setBoolValue(retval, ld != rd);
  1623. return true;
  1624. case PGBENCH_LE:
  1625. setBoolValue(retval, ld <= rd);
  1626. return true;
  1627. case PGBENCH_LT:
  1628. setBoolValue(retval, ld < rd);
  1629. return true;
  1630. default:
  1631. /* cannot get here */
  1632. Assert(0);
  1633. }
  1634. }
  1635. else /* we have integer operands, or % */
  1636. {
  1637. int64 li,
  1638. ri;
  1639. if (!coerceToInt(lval, &li) ||
  1640. !coerceToInt(rval, &ri))
  1641. return false;
  1642. switch (func)
  1643. {
  1644. case PGBENCH_ADD:
  1645. setIntValue(retval, li + ri);
  1646. return true;
  1647. case PGBENCH_SUB:
  1648. setIntValue(retval, li - ri);
  1649. return true;
  1650. case PGBENCH_MUL:
  1651. setIntValue(retval, li * ri);
  1652. return true;
  1653. case PGBENCH_EQ:
  1654. setBoolValue(retval, li == ri);
  1655. return true;
  1656. case PGBENCH_NE:
  1657. setBoolValue(retval, li != ri);
  1658. return true;
  1659. case PGBENCH_LE:
  1660. setBoolValue(retval, li <= ri);
  1661. return true;
  1662. case PGBENCH_LT:
  1663. setBoolValue(retval, li

Large files files are truncated, but you can click here to view the full file