v38 is a simple rebase, trying to keep up-to-date with Tom's work.

v39 is yet another rebase: 42 is in sight!

--
Fabien.
diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml
index c6d1454..4ceddae 100644
--- a/doc/src/sgml/ref/pgbench.sgml
+++ b/doc/src/sgml/ref/pgbench.sgml
@@ -815,9 +815,10 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
 
     <listitem>
      <para>
-      Sets variable <replaceable>varname</> to an integer value calculated
+      Sets variable <replaceable>varname</> to a value calculated
       from <replaceable>expression</>.
       The expression may contain integer constants such as <literal>5432</>,
+      double constants such as <literal>3.14159</>,
       references to variables <literal>:</><replaceable>variablename</>,
       unary operators (<literal>+</>, <literal>-</>) and binary operators
       (<literal>+</>, <literal>-</>, <literal>*</>, <literal>/</>,
@@ -830,7 +831,7 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
       Examples:
 <programlisting>
 \set ntellers 10 * :scale
-\set aid (1021 * :aid) % (100000 * :scale) + 1
+\set aid (1021 * random(1, 100000 * :scale)) % (100000 * :scale) + 1
 </programlisting></para>
     </listitem>
    </varlistentry>
@@ -850,66 +851,35 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
      </para>
 
      <para>
-      By default, or when <literal>uniform</> is specified, all values in the
-      range are drawn with equal probability.  Specifying <literal>gaussian</>
-      or  <literal>exponential</> options modifies this behavior; each
-      requires a mandatory parameter which determines the precise shape of the
-      distribution.
-     </para>
+      <itemizedlist>
+       <listitem>
+        <para>
+         <literal>\setrandom n 1 10</> or <literal>\setrandom n 1 10 uniform</>
+         is equivalent to <literal>\set n random(1, 10)</> and uses a uniform
+         distribution.
+        </para>
+       </listitem>
 
-     <para>
-      For a Gaussian distribution, the interval is mapped onto a standard
-      normal distribution (the classical bell-shaped Gaussian curve) truncated
-      at <literal>-parameter</> on the left and <literal>+parameter</>
-      on the right.
-      Values in the middle of the interval are more likely to be drawn.
-      To be precise, if <literal>PHI(x)</> is the cumulative distribution
-      function of the standard normal distribution, with mean <literal>mu</>
-      defined as <literal>(max + min) / 2.0</>, with
-<literallayout>
- f(x) = PHI(2.0 * parameter * (x - mu) / (max - min + 1)) /
-        (2.0 * PHI(parameter) - 1.0)
-</literallayout>
-      then value <replaceable>i</> between <replaceable>min</> and
-      <replaceable>max</> inclusive is drawn with probability:
-      <literal>f(i + 0.5) - f(i - 0.5)</>.
-      Intuitively, the larger <replaceable>parameter</>, the more
-      frequently values close to the middle of the interval are drawn, and the
-      less frequently values close to the <replaceable>min</> and
-      <replaceable>max</> bounds. About 67% of values are drawn from the
-      middle <literal>1.0 / parameter</>, that is a relative
-      <literal>0.5 / parameter</> around the mean, and 95% in the middle
-      <literal>2.0 / parameter</>, that is a relative
-      <literal>1.0 / parameter</> around the mean; for instance, if
-      <replaceable>parameter</> is 4.0, 67% of values are drawn from the
-      middle quarter (1.0 / 4.0) of the interval (i.e. from
-      <literal>3.0 / 8.0</> to <literal>5.0 / 8.0</>) and 95% from
-      the middle half (<literal>2.0 / 4.0</>) of the interval (second and
-      third quartiles). The minimum <replaceable>parameter</> is 2.0 for
-      performance of the Box-Muller transform.
-     </para>
+      <listitem>
+       <para>
+        <literal>\setrandom n 1 10 exponential 3.0</> is equivalent to
+        <literal>\set n random_exponential(1, 10, 3.0)</> and uses an
+        exponential distribution.
+       </para>
+      </listitem>
 
-     <para>
-      For an exponential distribution, <replaceable>parameter</>
-      controls the distribution by truncating a quickly-decreasing
-      exponential distribution at <replaceable>parameter</>, and then
-      projecting onto integers between the bounds.
-      To be precise, with
-<literallayout>
-f(x) = exp(-parameter * (x - min) / (max - min + 1)) / (1.0 - exp(-parameter))
-</literallayout>
-      Then value <replaceable>i</> between <replaceable>min</> and
-      <replaceable>max</> inclusive is drawn with probability:
-      <literal>f(x) - f(x + 1)</>.
-      Intuitively, the larger <replaceable>parameter</>, the more
-      frequently values close to <replaceable>min</> are accessed, and the
-      less frequently values close to <replaceable>max</> are accessed.
-      The closer to 0 <replaceable>parameter</>, the flatter (more uniform)
-      the access distribution.
-      A crude approximation of the distribution is that the most frequent 1%
-      values in the range, close to <replaceable>min</>, are drawn
-      <replaceable>parameter</>% of the time.
-      <replaceable>parameter</> value must be strictly positive.
+      <listitem>
+       <para>
+        <literal>\setrandom n 1 10 gaussian 2.0</> is equivalent to
+        <literal>\set n random_gaussian(1, 10, 2.0)</>, and uses a gaussian
+        distribution.
+       </para>
+      </listitem>
+     </itemizedlist>
+
+       See the documentation of these functions below for further information
+       about the precise shape of these distributions, depending on the value
+       of the parameter.
      </para>
 
      <para>
@@ -990,34 +960,6 @@ f(x) = exp(-parameter * (x - min) / (max - min + 1)) / (1.0 - exp(-parameter))
     </listitem>
    </varlistentry>
   </variablelist>
-
-  <para>
-   As an example, the full definition of the built-in TPC-B-like
-   transaction is:
-
-<programlisting>
-\set nbranches :scale
-\set ntellers 10 * :scale
-\set naccounts 100000 * :scale
-\setrandom aid 1 :naccounts
-\setrandom bid 1 :nbranches
-\setrandom tid 1 :ntellers
-\setrandom delta -5000 5000
-BEGIN;
-UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
-SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
-UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
-UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
-INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
-END;
-</programlisting>
-
-   This script allows each iteration of the transaction to reference
-   different, randomly-chosen rows.  (This example also shows why it's
-   important for each client session to have its own variables &mdash;
-   otherwise they'd not be independently touching different rows.)
-  </para>
-
  </refsect2>
 
  <refsect2 id="pgbench-builtin-functions">
@@ -1046,7 +988,7 @@ END;
       <row>
        <entry><literal><function>abs(<replaceable>a</>)</></></>
        <entry>same as <replaceable>a</></>
-       <entry>integer value</>
+       <entry>integer or double absolute value</>
        <entry><literal>abs(-17)</></>
        <entry><literal>17</></>
       </row>
@@ -1054,8 +996,22 @@ END;
        <entry><literal><function>debug(<replaceable>a</>)</></></>
        <entry>same as <replaceable>a</> </>
        <entry>print to <systemitem>stderr</systemitem> the given argument</>
-       <entry><literal>debug(5432)</></>
-       <entry><literal>5432</></>
+       <entry><literal>debug(5432.1)</></>
+       <entry><literal>5432.1</></>
+      </row>
+      <row>
+       <entry><literal><function>double(<replaceable>i</>)</></></>
+       <entry>double</>
+       <entry>cast to double</>
+       <entry><literal>double(5432)</></>
+       <entry><literal>5432.0</></>
+      </row>
+      <row>
+       <entry><literal><function>int(<replaceable>x</>)</></></>
+       <entry>integer</>
+       <entry>cast to int</>
+       <entry><literal>int(5.4 + 3.8)</></>
+       <entry><literal>9</></>
       </row>
       <row>
        <entry><literal><function>max(<replaceable>i</> [, <replaceable>...</> ] )</></></>
@@ -1071,9 +1027,143 @@ END;
        <entry><literal>min(5, 4, 3, 2)</></>
        <entry><literal>2</></>
       </row>
+      <row>
+       <entry><literal><function>pi()</></></>
+       <entry>double</>
+       <entry>value of the PI constant</>
+       <entry><literal>pi()</></>
+       <entry><literal>3.14159265358979323846</></>
+      </row>
+      <row>
+       <entry><literal><function>random(<replaceable>lb</>, <replaceable>ub</>)</></></>
+       <entry>integer</>
+       <entry>uniformly-distributed random integer in <literal>[lb, ub]</></>
+       <entry><literal>random(1, 10)</></>
+       <entry>an integer between <literal>1</> and <literal>10</></>
+      </row>
+      <row>
+       <entry><literal><function>random_exponential(<replaceable>lb</>, <replaceable>ub</>, <replaceable>parameter</>)</></></>
+       <entry>integer</>
+       <entry>exponentially-distributed random integer in <literal>[lb, ub]</>,
+              see below</>
+       <entry><literal>random_exponential(1, 10, 3.0)</></>
+       <entry>an integer between <literal>1</> and <literal>10</></>
+      </row>
+      <row>
+       <entry><literal><function>random_gaussian(<replaceable>lb</>, <replaceable>ub</>, <replaceable>parameter</>)</></></>
+       <entry>integer</>
+       <entry>gaussian-distributed random integer in <literal>[lb, ub]</>,
+              see below</>
+       <entry><literal>random_gaussian(1, 10, 2.5)</></>
+       <entry>an integer between <literal>1</> and <literal>10</></>
+      </row>
+      <row>
+       <entry><literal><function>sqrt(<replaceable>x</>)</></></>
+       <entry>double</>
+       <entry>square root</>
+       <entry><literal>sqrt(2.0)</></>
+       <entry><literal>1.414213562</></>
+      </row>
      </tbody>
      </tgroup>
    </table>
+
+   <para>
+    The <literal>random</> function generates values using a uniform
+    distribution, that is all the values are drawn within the specified
+    range with equal probability. The <literal>random_exponential</> and
+    <literal>random_gaussian</> functions require an additional double
+    parameter which determines the precise shape of the distribution.
+   </para>
+
+   <itemizedlist>
+    <listitem>
+     <para>
+      For an exponential distribution, <replaceable>parameter</>
+      controls the distribution by truncating a quickly-decreasing
+      exponential distribution at <replaceable>parameter</>, and then
+      projecting onto integers between the bounds.
+      To be precise, with
+<literallayout>
+f(x) = exp(-parameter * (x - min) / (max - min + 1)) / (1 - exp(-parameter))
+</literallayout>
+      Then value <replaceable>i</> between <replaceable>min</> and
+      <replaceable>max</> inclusive is drawn with probability:
+      <literal>f(x) - f(x + 1)</>.
+     </para>
+
+     <para>
+      Intuitively, the larger the <replaceable>parameter</>, the more
+      frequently values close to <replaceable>min</> are accessed, and the
+      less frequently values close to <replaceable>max</> are accessed.
+      The closer to 0 <replaceable>parameter</> is, the flatter (more
+      uniform) the access distribution.
+      A crude approximation of the distribution is that the most frequent 1%
+      values in the range, close to <replaceable>min</>, are drawn
+      <replaceable>parameter</>% of the time.
+      The <replaceable>parameter</> value must be strictly positive.
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      For a Gaussian distribution, the interval is mapped onto a standard
+      normal distribution (the classical bell-shaped Gaussian curve) truncated
+      at <literal>-parameter</> on the left and <literal>+parameter</>
+      on the right.
+      Values in the middle of the interval are more likely to be drawn.
+      To be precise, if <literal>PHI(x)</> is the cumulative distribution
+      function of the standard normal distribution, with mean <literal>mu</>
+      defined as <literal>(max + min) / 2.0</>, with
+<literallayout>
+ f(x) = PHI(2.0 * parameter * (x - mu) / (max - min + 1)) /
+        (2.0 * PHI(parameter) - 1)
+</literallayout>
+      then value <replaceable>i</> between <replaceable>min</> and
+      <replaceable>max</> inclusive is drawn with probability:
+      <literal>f(i + 0.5) - f(i - 0.5)</>.
+      Intuitively, the larger the <replaceable>parameter</>, the more
+      frequently values close to the middle of the interval are drawn, and the
+      less frequently values close to the <replaceable>min</> and
+      <replaceable>max</> bounds. About 67% of values are drawn from the
+      middle <literal>1.0 / parameter</>, that is a relative
+      <literal>0.5 / parameter</> around the mean, and 95% in the middle
+      <literal>2.0 / parameter</>, that is a relative
+      <literal>1.0 / parameter</> around the mean; for instance, if
+      <replaceable>parameter</> is 4.0, 67% of values are drawn from the
+      middle quarter (1.0 / 4.0) of the interval (i.e. from
+      <literal>3.0 / 8.0</> to <literal>5.0 / 8.0</>) and 95% from
+      the middle half (<literal>2.0 / 4.0</>) of the interval (second and third
+      quartiles). The minimum <replaceable>parameter</> is 2.0 for performance
+      of the Box-Muller transform.
+     </para>
+    </listitem>
+   </itemizedlist>
+
+  <para>
+   As an example, the full definition of the built-in TPC-B-like
+   transaction is:
+
+<programlisting>
+\set aid random(1, 100000 * :scale)
+\set bid random(1, 1 * :scale)
+\set tid random(1, 10 * :scale)
+\set delta random(-5000, 5000)
+BEGIN;
+UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
+SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
+UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
+UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
+INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
+END;
+</programlisting>
+
+   This script allows each iteration of the transaction to reference
+   different, randomly-chosen rows.  (This example also shows why it's
+   important for each client session to have its own variables &mdash;
+   otherwise they'd not be independently touching different rows.)
+  </para>
+
  </refsect2>
 
  <refsect2>
@@ -1223,13 +1313,10 @@ tps = 618.764555 (including connections establishing)
 tps = 622.977698 (excluding connections establishing)
 script statistics:
  - statement latencies in milliseconds:
-        0.004386        \set nbranches 1 * :scale
-        0.001343        \set ntellers 10 * :scale
-        0.001212        \set naccounts 100000 * :scale
-        0.001310        \setrandom aid 1 :naccounts
-        0.001073        \setrandom bid 1 :nbranches
-        0.001005        \setrandom tid 1 :ntellers
-        0.001078        \setrandom delta -5000 5000
+        0.002522        \set aid random(1, 100000 * :scale)
+        0.005459        \set bid random(1, 1 * :scale)
+        0.002348        \set tid random(1, 10 * :scale)
+        0.001078        \set delta random(-5000, 5000)
         0.326152        BEGIN;
         0.603376        UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
         0.454643        SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
diff --git a/src/bin/pgbench/exprparse.y b/src/bin/pgbench/exprparse.y
index 5d0d972..d7ae005 100644
--- a/src/bin/pgbench/exprparse.y
+++ b/src/bin/pgbench/exprparse.y
@@ -20,6 +20,7 @@ PgBenchExpr *expr_parse_result;
 
 static PgBenchExprList *make_elist(PgBenchExpr *exp, PgBenchExprList *list);
 static PgBenchExpr *make_integer_constant(int64 ival);
+static PgBenchExpr *make_double_constant(double dval);
 static PgBenchExpr *make_variable(char *varname);
 static PgBenchExpr *make_op(yyscan_t yyscanner, const char *operator,
 		PgBenchExpr *lexpr, PgBenchExpr *rexpr);
@@ -37,6 +38,7 @@ static PgBenchExpr *make_func(yyscan_t yyscanner, int fnumber, PgBenchExprList *
 %union
 {
 	int64		ival;
+	double		dval;
 	char	   *str;
 	PgBenchExpr *expr;
 	PgBenchExprList *elist;
@@ -45,9 +47,10 @@ static PgBenchExpr *make_func(yyscan_t yyscanner, int fnumber, PgBenchExprList *
 %type <elist> elist
 %type <expr> expr
 %type <ival> INTEGER function
+%type <dval> DOUBLE
 %type <str> VARIABLE FUNCTION
 
-%token INTEGER VARIABLE FUNCTION
+%token INTEGER DOUBLE VARIABLE FUNCTION
 
 /* Precedence: lowest to highest */
 %left	'+' '-'
@@ -73,6 +76,7 @@ expr: '(' expr ')'			{ $$ = $2; }
 	| expr '/' expr			{ $$ = make_op(yyscanner, "/", $1, $3); }
 	| expr '%' expr			{ $$ = make_op(yyscanner, "%", $1, $3); }
 	| INTEGER				{ $$ = make_integer_constant($1); }
+	| DOUBLE				{ $$ = make_double_constant($1); }
 	| VARIABLE 				{ $$ = make_variable($1); }
 	| function '(' elist ')' { $$ = make_func(yyscanner, $1, $3); }
 	;
@@ -87,8 +91,20 @@ make_integer_constant(int64 ival)
 {
 	PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
 
-	expr->etype = ENODE_INTEGER_CONSTANT;
-	expr->u.integer_constant.ival = ival;
+	expr->etype = ENODE_CONSTANT;
+	expr->u.constant.type = PGBT_INT;
+	expr->u.constant.u.ival = ival;
+	return expr;
+}
+
+static PgBenchExpr *
+make_double_constant(double dval)
+{
+	PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
+
+	expr->etype = ENODE_CONSTANT;
+	expr->u.constant.type = PGBT_DOUBLE;
+	expr->u.constant.u.dval = dval;
 	return expr;
 }
 
@@ -153,6 +169,27 @@ static const struct
 	{
 		"debug", 1, PGBENCH_DEBUG
 	},
+	{
+		"pi", 0, PGBENCH_PI
+	},
+	{
+		"sqrt", 1, PGBENCH_SQRT
+	},
+	{
+		"int", 1, PGBENCH_INT
+	},
+	{
+		"double", 1, PGBENCH_DOUBLE
+	},
+	{
+		"random", 2, PGBENCH_RANDOM
+	},
+	{
+		"random_gaussian", 3, PGBENCH_RANDOM_GAUSSIAN
+	},
+	{
+		"random_exponential", 3, PGBENCH_RANDOM_EXPONENTIAL
+	},
 	/* keep as last array element */
 	{
 		NULL, 0, 0
diff --git a/src/bin/pgbench/exprscan.l b/src/bin/pgbench/exprscan.l
index d069c5b..3965369 100644
--- a/src/bin/pgbench/exprscan.l
+++ b/src/bin/pgbench/exprscan.l
@@ -124,6 +124,11 @@ newline			[\n]
 					yylval.ival = strtoint64(yytext);
 					return INTEGER;
 				}
+{digit}+(\.{digit}*)?([eE][-+]?{digit}+)?	{
+					yycolumn += yyleng;
+					yylval.dval = atof(yytext);
+					return DOUBLE;
+				}
 {alpha}{alnum}*	{
 					yylval.str = pg_strdup(yytext);
 					return FUNCTION;
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 4196b0e..93c72e0 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -328,13 +328,10 @@ static const BuiltinScript builtin_script[] =
 	{
 		"tpcb-like",
 		"<builtin: TPC-B (sort of)>",
-		"\\set nbranches " CppAsString2(nbranches) " * :scale\n"
-		"\\set ntellers " CppAsString2(ntellers) " * :scale\n"
-		"\\set naccounts " CppAsString2(naccounts) " * :scale\n"
-		"\\setrandom aid 1 :naccounts\n"
-		"\\setrandom bid 1 :nbranches\n"
-		"\\setrandom tid 1 :ntellers\n"
-		"\\setrandom delta -5000 5000\n"
+		"\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
+		"\\set bid random(1, " CppAsString2(nbranches) " * :scale)\n"
+		"\\set tid random(1, " CppAsString2(ntellers) " * :scale)\n"
+		"\\set delta random(-5000, 5000)\n"
 		"BEGIN;\n"
 		"UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
 		"SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
@@ -346,13 +343,10 @@ static const BuiltinScript builtin_script[] =
 	{
 		"simple-update",
 		"<builtin: simple update>",
-		"\\set nbranches " CppAsString2(nbranches) " * :scale\n"
-		"\\set ntellers " CppAsString2(ntellers) " * :scale\n"
-		"\\set naccounts " CppAsString2(naccounts) " * :scale\n"
-		"\\setrandom aid 1 :naccounts\n"
-		"\\setrandom bid 1 :nbranches\n"
-		"\\setrandom tid 1 :ntellers\n"
-		"\\setrandom delta -5000 5000\n"
+		"\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
+		"\\set bid random(1, " CppAsString2(nbranches) " * :scale)\n"
+		"\\set tid random(1, " CppAsString2(ntellers) " * :scale)\n"
+		"\\set delta random(-5000, 5000)\n"
 		"BEGIN;\n"
 		"UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
 		"SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
@@ -362,15 +356,14 @@ static const BuiltinScript builtin_script[] =
 	{
 		"select-only",
 		"<builtin: select only>",
-		"\\set naccounts " CppAsString2(naccounts) " * :scale\n"
-		"\\setrandom aid 1 :naccounts\n"
+		"\\set aid random(1, " CppAsString2(naccounts) " * :scale)\n"
 		"SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
 	}
 };
 
 
 /* Function prototypes */
-static bool evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval);
+static bool evaluateExpr(TState *, CState *, PgBenchExpr *, PgBenchValue *);
 static void doLog(TState *thread, CState *st, instr_time *now,
 	  StatsData *agg, bool skipped, double latency, double lag);
 static void processXactStats(TState *thread, CState *st, instr_time *now,
@@ -380,14 +373,12 @@ static void addScript(ParsedScript script);
 static void *threadRun(void *arg);
 static void setalarm(int seconds);
 
-
 /* callback functions for our flex lexer */
 static const PsqlScanCallbacks pgbench_callbacks = {
 	NULL,						/* don't need get_variable functionality */
 	pgbench_error
 };
 
-
 static void
 usage(void)
 {
@@ -446,6 +437,33 @@ usage(void)
 		   progname, progname);
 }
 
+/* return whether str matches "^\s*[-+]?[0-9]+$" */
+static bool
+is_an_int(const char *str)
+{
+	const char *ptr = str;
+
+	/* skip leading spaces; cast is consistent with strtoint64 */
+	while (*ptr && isspace((unsigned char) *ptr))
+		ptr++;
+
+	/* skip sign */
+	if (*ptr == '+' || *ptr == '-')
+		ptr++;
+
+	/* at least one digit */
+	if (*ptr && !isdigit((unsigned char) *ptr))
+		return false;
+
+	/* eat all digits */
+	while (*ptr && isdigit((unsigned char) *ptr))
+		ptr++;
+
+	/* must have reached end of string */
+	return *ptr == '\0';
+}
+
+
 /*
  * strtoint64 -- convert a string to 64-bit integer
  *
@@ -542,6 +560,7 @@ getExponentialRand(TState *thread, int64 min, int64 max, double parameter)
 				uniform,
 				rand;
 
+	/* abort if wrong parameter, but must really be checked beforehand */
 	Assert(parameter > 0.0);
 	cut = exp(-parameter);
 	/* erand in [0, 1), uniform in (0, 1] */
@@ -563,6 +582,9 @@ getGaussianRand(TState *thread, int64 min, int64 max, double parameter)
 	double		stdev;
 	double		rand;
 
+	/* abort if parameter is too low, but must really be checked beforehand */
+	Assert(parameter >= MIN_GAUSSIAN_PARAM);
+
 	/*
 	 * Get user specified random number from this loop, with -parameter <
 	 * stdev <= parameter
@@ -1006,6 +1028,62 @@ getQueryParams(CState *st, const Command *command, const char **params)
 		params[i] = getVariable(st, command->argv[i + 1]);
 }
 
+/* get a value as an int, tell if there is a problem */
+static bool
+coerceToInt(CState *st, PgBenchValue *pval, int64 *ival)
+{
+	if (pval->type == PGBT_INT)
+	{
+		*ival = pval->u.ival;
+		return true;
+	}
+	else
+	{
+		double dval = pval->u.dval;
+		Assert(pval->type == PGBT_DOUBLE);
+		if (dval < INT64_MIN || INT64_MAX < dval)
+		{
+			fprintf(stderr, "double to int overflow for %f\n", dval);
+			return false;
+		}
+		*ival = (int64) dval;
+		return true;
+	}
+}
+
+/* get a value as a double, or tell if there is a problem */
+static bool
+coerceToDouble(CState *st, PgBenchValue *pval, double *dval)
+{
+	if (pval->type == PGBT_DOUBLE)
+	{
+		*dval = pval->u.dval;
+		return true;
+	}
+	else
+	{
+		Assert(pval->type == PGBT_INT);
+		*dval = (double) pval->u.ival;
+		return true;
+	}
+}
+
+/* assign an integer value */
+static void
+setIntValue(PgBenchValue *pv, int64 ival)
+{
+	pv->type = PGBT_INT;
+	pv->u.ival = ival;
+}
+
+/* assign a double value */
+static void
+setDoubleValue(PgBenchValue *pv, double dval)
+{
+	pv->type = PGBT_DOUBLE;
+	pv->u.dval = dval;
+}
+
 /* maximum number of function arguments */
 #define MAX_FARGS 16
 
@@ -1013,16 +1091,16 @@ getQueryParams(CState *st, const Command *command, const char **params)
  * Recursive evaluation of functions
  */
 static bool
-evalFunc(CState *st,
-		 PgBenchFunction func, PgBenchExprLink *args, int64 *retval)
+evalFunc(TState *thread, CState *st,
+		 PgBenchFunction func, PgBenchExprLink *args, PgBenchValue *retval)
 {
 	/* evaluate all function arguments */
-	int			nargs = 0;
-	int64		iargs[MAX_FARGS];
+	int	 			nargs = 0;
+	PgBenchValue 	vargs[MAX_FARGS];
 	PgBenchExprLink *l = args;
 
 	for (nargs = 0; nargs < MAX_FARGS && l != NULL; nargs++, l = l->next)
-		if (!evaluateExpr(st, l->expr, &iargs[nargs]))
+		if (!evaluateExpr(thread, st, l->expr, &vargs[nargs]))
 			return false;
 
 	if (l != NULL)
@@ -1035,104 +1113,206 @@ evalFunc(CState *st,
 	/* then evaluate function */
 	switch (func)
 	{
+		/* overloaded operators */
 		case PGBENCH_ADD:
 		case PGBENCH_SUB:
 		case PGBENCH_MUL:
 		case PGBENCH_DIV:
 		case PGBENCH_MOD:
 			{
-				int64		lval = iargs[0],
-							rval = iargs[1];
-
+				PgBenchValue	*lval = &vargs[0],
+								*rval = &vargs[1];
 				Assert(nargs == 2);
 
-				switch (func)
+				/* overloaded type management, double if some double */
+				if ((lval->type == PGBT_DOUBLE ||
+					 rval->type == PGBT_DOUBLE) && func != PGBENCH_MOD)
 				{
-					case PGBENCH_ADD:
-						*retval = lval + rval;
-						return true;
-
-					case PGBENCH_SUB:
-						*retval = lval - rval;
-						return true;
-
-					case PGBENCH_MUL:
-						*retval = lval * rval;
-						return true;
-
-					case PGBENCH_DIV:
-					case PGBENCH_MOD:
-						if (rval == 0)
-						{
-							fprintf(stderr, "division by zero\n");
-							return false;
-						}
-						/* special handling of -1 divisor */
-						if (rval == -1)
-						{
-							if (func == PGBENCH_DIV)
+					double ld, rd;
+
+					if (!coerceToDouble(st, lval, &ld) ||
+						!coerceToDouble(st, rval, &rd))
+						return false;
+
+					switch (func)
+					{
+						case PGBENCH_ADD:
+							setDoubleValue(retval, ld + rd);
+							return true;
+
+						case PGBENCH_SUB:
+							setDoubleValue(retval, ld - rd);
+							return true;
+
+						case PGBENCH_MUL:
+							setDoubleValue(retval, ld * rd);
+							return true;
+
+						case PGBENCH_DIV:
+							setDoubleValue(retval, ld / rd);
+							return true;
+
+						default:
+							/* cannot get here */
+							Assert(0);
+					}
+				}
+				else  /* we have integer operands, or % */
+				{
+					int64 li, ri;
+
+					if (!coerceToInt(st, lval, &li) ||
+						!coerceToInt(st, rval, &ri))
+						return false;
+
+					switch (func)
+					{
+						case PGBENCH_ADD:
+							setIntValue(retval, li + ri);
+							return true;
+
+						case PGBENCH_SUB:
+							setIntValue(retval, li - ri);
+							return true;
+
+						case PGBENCH_MUL:
+							setIntValue(retval, li * ri);
+							return true;
+
+						case PGBENCH_DIV:
+						case PGBENCH_MOD:
+							if (ri == 0)
+							{
+								fprintf(stderr, "division by zero\n");
+								return false;
+							}
+							/* special handling of -1 divisor */
+							if (ri == -1)
 							{
-								/* overflow check (needed for INT64_MIN) */
-								if (lval == PG_INT64_MIN)
+								if (func == PGBENCH_DIV)
 								{
-									fprintf(stderr, "bigint out of range\n");
-									return false;
+									/* overflow check (needed for INT64_MIN) */
+									if (li == PG_INT64_MIN)
+									{
+										fprintf(stderr, "bigint out of range\n");
+										return false;
+									}
+									else
+										setIntValue(retval, - li);
 								}
 								else
-									*retval = -lval;
+									setIntValue(retval, 0);
+								return true;
 							}
-							else
-								*retval = 0;
+							/* else divisor is not -1 */
+							if (func == PGBENCH_DIV)
+								setIntValue(retval, li / ri);
+							else /* func == PGBENCH_MOD */
+								setIntValue(retval, li % ri);
+
 							return true;
-						}
-						/* divisor is not -1 */
-						if (func == PGBENCH_DIV)
-							*retval = lval / rval;
-						else	/* func == PGBENCH_MOD */
-							*retval = lval % rval;
-						return true;
 
-					default:
-						/* cannot get here */
-						Assert(0);
+						default:
+							/* cannot get here */
+							Assert(0);
+					}
 				}
 			}
 
+		/* no arguments */
+		case PGBENCH_PI:
+			setDoubleValue(retval, M_PI);
+			return true;
+
+		/* 1 overloaded argument */
 		case PGBENCH_ABS:
 			{
+				PgBenchValue *varg = &vargs[0];
 				Assert(nargs == 1);
 
-				if (iargs[0] < 0)
-					*retval = -iargs[0];
+				if (varg->type == PGBT_INT)
+				{
+					int64 i = varg->u.ival;
+					setIntValue(retval, i < 0 ? -i : i);
+				}
 				else
-					*retval = iargs[0];
+				{
+					double d = varg->u.dval;
+					Assert(varg->type == PGBT_DOUBLE);
+					setDoubleValue(retval, d < 0.0 ? -d: d);
+				}
 
 				return true;
 			}
 
 		case PGBENCH_DEBUG:
 			{
+				PgBenchValue *varg = &vargs[0];
 				Assert(nargs == 1);
 
-				fprintf(stderr, "debug(script=%d,command=%d): " INT64_FORMAT "\n",
-						st->use_file, st->state + 1, iargs[0]);
+				fprintf(stderr,	"debug(script=%d,command=%d): ",
+						st->use_file, st->state+1);
 
-				*retval = iargs[0];
+				if (varg->type == PGBT_INT)
+					fprintf(stderr,	"int "INT64_FORMAT"\n", varg->u.ival);
+				else
+				{
+					Assert(varg->type == PGBT_DOUBLE);
+					fprintf(stderr, "double %f\n", varg->u.dval);
+				}
 
+				*retval = *varg;
+
+				return true;
+			}
+
+		/* 1 double argument */
+		case PGBENCH_DOUBLE:
+		case PGBENCH_SQRT:
+			{
+				double dval;
+				Assert(nargs == 1);
+
+				if (!coerceToDouble(st, &vargs[0], &dval))
+					return false;
+
+				if (func == PGBENCH_SQRT)
+					dval = sqrt(dval);
+
+				setDoubleValue(retval, dval);
+				return true;
+			}
+
+		/* 1 int argument */
+		case PGBENCH_INT:
+			{
+				int64 ival;
+				Assert(nargs == 1);
+
+				if (!coerceToInt(st, &vargs[0], &ival))
+					return false;
+
+				setIntValue(retval, ival);
 				return true;
 			}
 
+		/* variable number of int arguments */
 		case PGBENCH_MIN:
 		case PGBENCH_MAX:
 			{
-				int64		extremum = iargs[0];
+				int64		extremum;
 				int			i;
-
 				Assert(nargs >= 1);
 
+				if (!coerceToInt(st, &vargs[0], &extremum))
+					return false;
+
 				for (i = 1; i < nargs; i++)
 				{
-					int64		ival = iargs[i];
+					int64		ival;
+
+					if (!coerceToInt(st, &vargs[i], &ival))
+						return false;
 
 					if (func == PGBENCH_MIN)
 						extremum = extremum < ival ? extremum : ival;
@@ -1140,13 +1320,84 @@ evalFunc(CState *st,
 						extremum = extremum > ival ? extremum : ival;
 				}
 
-				*retval = extremum;
+				setIntValue(retval, extremum);
 				return true;
 			}
 
+		/* random functions */
+		case PGBENCH_RANDOM:
+		case PGBENCH_RANDOM_EXPONENTIAL:
+		case PGBENCH_RANDOM_GAUSSIAN:
+		{
+			int64       imin, imax;
+			Assert(nargs >= 2);
+
+			if (!coerceToInt(st, &vargs[0], &imin) ||
+				!coerceToInt(st, &vargs[1], &imax))
+				return false;
+
+			/* check random range */
+			if (imin > imax)
+			{
+				fprintf(stderr, "empty range given to random\n");
+				return false;
+			}
+			else if (imax - imin < 0 || (imax - imin) + 1 < 0)
+			{
+				/* prevent int overflows in random functions */
+				fprintf(stderr, "random range is too large\n");
+				return false;
+			}
+
+			if (func == PGBENCH_RANDOM)
+			{
+				Assert(nargs == 2);
+				setIntValue(retval, getrand(thread, imin, imax));
+			}
+			else /* gaussian & exponential */
+			{
+				double param;
+				Assert(nargs == 3);
+
+				if (!coerceToDouble(st, &vargs[2], &param))
+					return false;
+
+				if (func == PGBENCH_RANDOM_GAUSSIAN)
+				{
+					if (param < MIN_GAUSSIAN_PARAM)
+					{
+						fprintf(stderr,
+								"gaussian parameter must be at least %f "
+								"(not %f)\n", MIN_GAUSSIAN_PARAM, param);
+						return false;
+					}
+
+					setIntValue(retval,
+								getGaussianRand(thread, imin, imax,	param));
+				}
+				else /* exponential */
+				{
+					if (param <= 0.0)
+					{
+						fprintf(stderr,
+								"exponential parameter must be greater than zero"
+								" (got %f)\n", param);
+						return false;
+					}
+
+					setIntValue(retval,
+								getExponentialRand(thread, imin, imax, param));
+				}
+			}
+
+			return true;
+		}
+
 		default:
-			fprintf(stderr, "unexpected function tag: %d\n", func);
-			exit(1);
+			/* cannot get here */
+			Assert(0);
+			/* dead code to avoid a compiler warning */
+			return false;
 	}
 }
 
@@ -1157,13 +1408,13 @@ evalFunc(CState *st,
  * the value itself is returned through the retval pointer.
  */
 static bool
-evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval)
+evaluateExpr(TState *thread, CState *st, PgBenchExpr *expr, PgBenchValue *retval)
 {
 	switch (expr->etype)
 	{
-		case ENODE_INTEGER_CONSTANT:
+		case ENODE_CONSTANT:
 			{
-				*retval = expr->u.integer_constant.ival;
+				*retval = expr->u.constant;
 				return true;
 			}
 
@@ -1177,24 +1428,39 @@ evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval)
 							expr->u.variable.varname);
 					return false;
 				}
-				*retval = strtoint64(var);
+
+				if (is_an_int(var))
+				{
+					setIntValue(retval, strtoint64(var));
+				}
+				else /* type should be double */
+				{
+					double dv;
+					if (sscanf(var, "%lf", &dv) != 1)
+					{
+						fprintf(stderr,
+								"malformed variable \"%s\" value: \"%s\"\n",
+								expr->u.variable.varname, var);
+						return false;
+					}
+					setDoubleValue(retval, dv);
+				}
+
 				return true;
 			}
 
 		case ENODE_FUNCTION:
-			return evalFunc(st,
+			return evalFunc(thread, st,
 							expr->u.function.function,
 							expr->u.function.args,
 							retval);
 
 		default:
+			/* internal error which should never occur */
 			fprintf(stderr, "unexpected enode type in evaluation: %d\n",
 					expr->etype);
 			exit(1);
 	}
-
-	fprintf(stderr, "bad expression\n");
-	return false;
 }
 
 /*
@@ -1673,6 +1939,10 @@ top:
 			fprintf(stderr, "\n");
 		}
 
+		/*
+		 * Note: this section could be removed, as the same functionnality
+		 * is available through \set xxx random_gaussian(...)
+		 */
 		if (pg_strcasecmp(argv[0], "setrandom") == 0)
 		{
 			char	   *var;
@@ -1814,15 +2084,21 @@ top:
 		{
 			char		res[64];
 			PgBenchExpr *expr = commands[st->state]->expr;
-			int64		result;
+			PgBenchValue	result;
 
-			if (!evaluateExpr(st, expr, &result))
+			if (!evaluateExpr(thread, st, expr, &result))
 			{
 				st->ecnt++;
 				return true;
 			}
 
-			sprintf(res, INT64_FORMAT, result);
+			if (result.type == PGBT_INT)
+				sprintf(res, INT64_FORMAT, result.u.ival);
+			else
+			{
+				Assert(result.type == PGBT_DOUBLE);
+				sprintf(res, "%.18e", result.u.dval);
+			}
 
 			if (!putVariable(st, argv[0], argv[1], res))
 			{
diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h
index a9db9c5..bd3afbe 100644
--- a/src/bin/pgbench/pgbench.h
+++ b/src/bin/pgbench/pgbench.h
@@ -22,10 +22,31 @@
  */
 #define yyscan_t  void *
 
+/*
+ * Variable types used in parser.
+ */
+typedef enum
+{
+	PGBT_INT,
+	PGBT_DOUBLE
+	/* add other types here */
+} PgBenchValueType;
+
+typedef struct
+{
+	PgBenchValueType type;
+	union
+	{
+		int64 ival;
+		double dval;
+		/* add other types here */
+	} u;
+} PgBenchValue;
+
 /* Types of expression nodes */
 typedef enum PgBenchExprType
 {
-	ENODE_INTEGER_CONSTANT,
+	ENODE_CONSTANT,
 	ENODE_VARIABLE,
 	ENODE_FUNCTION
 } PgBenchExprType;
@@ -42,6 +63,13 @@ typedef enum PgBenchFunction
 	PGBENCH_ABS,
 	PGBENCH_MIN,
 	PGBENCH_MAX,
+	PGBENCH_INT,
+	PGBENCH_DOUBLE,
+	PGBENCH_PI,
+	PGBENCH_SQRT,
+	PGBENCH_RANDOM,
+	PGBENCH_RANDOM_GAUSSIAN,
+	PGBENCH_RANDOM_EXPONENTIAL
 } PgBenchFunction;
 
 typedef struct PgBenchExpr PgBenchExpr;
@@ -53,10 +81,7 @@ struct PgBenchExpr
 	PgBenchExprType etype;
 	union
 	{
-		struct
-		{
-			int64		ival;
-		}			integer_constant;
+		PgBenchValue	constant;
 		struct
 		{
 			char	   *varname;
diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml
index 4ceddae..c5399ff 100644
--- a/doc/src/sgml/ref/pgbench.sgml
+++ b/doc/src/sgml/ref/pgbench.sgml
@@ -838,60 +838,6 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
 
    <varlistentry>
     <term>
-     <literal>\setrandom <replaceable>varname</> <replaceable>min</> <replaceable>max</> [ uniform | { gaussian | exponential } <replaceable>parameter</> ]</literal>
-     </term>
-
-    <listitem>
-     <para>
-      Sets variable <replaceable>varname</> to a random integer value
-      between the limits <replaceable>min</> and <replaceable>max</> inclusive.
-      Each limit can be either an integer constant or a
-      <literal>:</><replaceable>variablename</> reference to a variable
-      having an integer value.
-     </para>
-
-     <para>
-      <itemizedlist>
-       <listitem>
-        <para>
-         <literal>\setrandom n 1 10</> or <literal>\setrandom n 1 10 uniform</>
-         is equivalent to <literal>\set n random(1, 10)</> and uses a uniform
-         distribution.
-        </para>
-       </listitem>
-
-      <listitem>
-       <para>
-        <literal>\setrandom n 1 10 exponential 3.0</> is equivalent to
-        <literal>\set n random_exponential(1, 10, 3.0)</> and uses an
-        exponential distribution.
-       </para>
-      </listitem>
-
-      <listitem>
-       <para>
-        <literal>\setrandom n 1 10 gaussian 2.0</> is equivalent to
-        <literal>\set n random_gaussian(1, 10, 2.0)</>, and uses a gaussian
-        distribution.
-       </para>
-      </listitem>
-     </itemizedlist>
-
-       See the documentation of these functions below for further information
-       about the precise shape of these distributions, depending on the value
-       of the parameter.
-     </para>
-
-     <para>
-      Example:
-<programlisting>
-\setrandom aid 1 :naccounts gaussian 5.0
-</programlisting></para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
      <literal>\sleep <replaceable>number</> [ us | ms | s ]</literal>
     </term>
 
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 93c72e0..21c5507 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -1939,148 +1939,7 @@ top:
 			fprintf(stderr, "\n");
 		}
 
-		/*
-		 * Note: this section could be removed, as the same functionnality
-		 * is available through \set xxx random_gaussian(...)
-		 */
-		if (pg_strcasecmp(argv[0], "setrandom") == 0)
-		{
-			char	   *var;
-			int64		min,
-						max;
-			double		parameter = 0;
-			char		res[64];
-
-			if (*argv[2] == ':')
-			{
-				if ((var = getVariable(st, argv[2] + 1)) == NULL)
-				{
-					fprintf(stderr, "%s: undefined variable \"%s\"\n",
-							argv[0], argv[2]);
-					st->ecnt++;
-					return true;
-				}
-				min = strtoint64(var);
-			}
-			else
-				min = strtoint64(argv[2]);
-
-			if (*argv[3] == ':')
-			{
-				if ((var = getVariable(st, argv[3] + 1)) == NULL)
-				{
-					fprintf(stderr, "%s: undefined variable \"%s\"\n",
-							argv[0], argv[3]);
-					st->ecnt++;
-					return true;
-				}
-				max = strtoint64(var);
-			}
-			else
-				max = strtoint64(argv[3]);
-
-			if (max < min)
-			{
-				fprintf(stderr, "%s: \\setrandom maximum is less than minimum\n",
-						argv[0]);
-				st->ecnt++;
-				return true;
-			}
-
-			/*
-			 * Generate random number functions need to be able to subtract
-			 * max from min and add one to the result without overflowing.
-			 * Since we know max > min, we can detect overflow just by
-			 * checking for a negative result. But we must check both that the
-			 * subtraction doesn't overflow, and that adding one to the result
-			 * doesn't overflow either.
-			 */
-			if (max - min < 0 || (max - min) + 1 < 0)
-			{
-				fprintf(stderr, "%s: \\setrandom range is too large\n",
-						argv[0]);
-				st->ecnt++;
-				return true;
-			}
-
-			if (argc == 4 ||	/* uniform without or with "uniform" keyword */
-				(argc == 5 && pg_strcasecmp(argv[4], "uniform") == 0))
-			{
-#ifdef DEBUG
-				printf("min: " INT64_FORMAT " max: " INT64_FORMAT " random: " INT64_FORMAT "\n", min, max, getrand(thread, min, max));
-#endif
-				snprintf(res, sizeof(res), INT64_FORMAT, getrand(thread, min, max));
-			}
-			else if (argc == 6 &&
-					 ((pg_strcasecmp(argv[4], "gaussian") == 0) ||
-					  (pg_strcasecmp(argv[4], "exponential") == 0)))
-			{
-				if (*argv[5] == ':')
-				{
-					if ((var = getVariable(st, argv[5] + 1)) == NULL)
-					{
-						fprintf(stderr, "%s: invalid parameter: \"%s\"\n",
-								argv[0], argv[5]);
-						st->ecnt++;
-						return true;
-					}
-					parameter = strtod(var, NULL);
-				}
-				else
-					parameter = strtod(argv[5], NULL);
-
-				if (pg_strcasecmp(argv[4], "gaussian") == 0)
-				{
-					if (parameter < MIN_GAUSSIAN_PARAM)
-					{
-						fprintf(stderr, "gaussian parameter must be at least %f (not \"%s\")\n", MIN_GAUSSIAN_PARAM, argv[5]);
-						st->ecnt++;
-						return true;
-					}
-#ifdef DEBUG
-					printf("min: " INT64_FORMAT " max: " INT64_FORMAT " random: " INT64_FORMAT "\n",
-						   min, max,
-						   getGaussianRand(thread, min, max, parameter));
-#endif
-					snprintf(res, sizeof(res), INT64_FORMAT,
-							 getGaussianRand(thread, min, max, parameter));
-				}
-				else if (pg_strcasecmp(argv[4], "exponential") == 0)
-				{
-					if (parameter <= 0.0)
-					{
-						fprintf(stderr,
-								"exponential parameter must be greater than zero (not \"%s\")\n",
-								argv[5]);
-						st->ecnt++;
-						return true;
-					}
-#ifdef DEBUG
-					printf("min: " INT64_FORMAT " max: " INT64_FORMAT " random: " INT64_FORMAT "\n",
-						   min, max,
-						   getExponentialRand(thread, min, max, parameter));
-#endif
-					snprintf(res, sizeof(res), INT64_FORMAT,
-							 getExponentialRand(thread, min, max, parameter));
-				}
-			}
-			else	/* this means an error somewhere in the parsing phase... */
-			{
-				fprintf(stderr, "%s: invalid arguments for \\setrandom\n",
-						argv[0]);
-				st->ecnt++;
-				return true;
-			}
-
-			if (!putVariable(st, argv[0], argv[1], res))
-			{
-				st->ecnt++;
-				return true;
-			}
-
-			st->listen = true;
-		}
-		else if (pg_strcasecmp(argv[0], "set") == 0)
+		if (pg_strcasecmp(argv[0], "set") == 0)
 		{
 			char		res[64];
 			PgBenchExpr *expr = commands[st->state]->expr;
@@ -2880,39 +2739,9 @@ process_backslash_command(PsqlScanState sstate, const char *source)
 
 	if (pg_strcasecmp(my_command->argv[0], "setrandom") == 0)
 	{
-		/*--------
-		 * parsing:
-		 *	 \setrandom variable min max [uniform]
-		 *	 \setrandom variable min max (gaussian|exponential) parameter
-		 */
-
-		if (my_command->argc < 4)
-			syntax_error(source, lineno, my_command->line, my_command->argv[0],
-						 "missing arguments", NULL, -1);
-
-		if (my_command->argc == 4 ||	/* uniform without/with "uniform"
-										 * keyword */
-			(my_command->argc == 5 &&
-			 pg_strcasecmp(my_command->argv[4], "uniform") == 0))
-		{
-			/* nothing to do */
-		}
-		else if (				/* argc >= 5 */
-				 (pg_strcasecmp(my_command->argv[4], "gaussian") == 0) ||
-				 (pg_strcasecmp(my_command->argv[4], "exponential") == 0))
-		{
-			if (my_command->argc < 6)
-				syntax_error(source, lineno, my_command->line, my_command->argv[0],
-							 "missing parameter", NULL, -1);
-			else if (my_command->argc > 6)
-				syntax_error(source, lineno, my_command->line, my_command->argv[0],
-							 "too many arguments", NULL,
-							 offsets[6] - start_offset);
-		}
-		else	/* unrecognized distribution argument */
-			syntax_error(source, lineno, my_command->line, my_command->argv[0],
-						 "unexpected argument", my_command->argv[4],
-						 offsets[4] - start_offset);
+		syntax_error(source, lineno, my_command->line, my_command->argv[0],
+					 "\\setrandom is not supported anymore, "
+					 "use \\set with the random() function\n", NULL, -1);
 	}
 	else if (pg_strcasecmp(my_command->argv[0], "sleep") == 0)
 	{
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to