Those can be avoided in other ways.  For example:

Ok, ok, I surrender:-)

Here is a v15 which hides conversions and assignment details in macros and factors out type testing of overloaded operators so that the code expansion is minimal (basically the operator evaluation is duplicated for int & double, but the rest is written once). The evaluation cost is probably slightly higher than the previous version because of the many hidden type tests.

Note that variables are only int stored as text. Another patch may try to propagate the value structure for variables, but then it changes the query expansion code, it is more or less orthogonal to add functions. Moreover double variables would not be really useful anyway.

--
Fabien.
diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml
index 0ac40f1..59445de 100644
--- a/doc/src/sgml/ref/pgbench.sgml
+++ b/doc/src/sgml/ref/pgbench.sgml
@@ -771,24 +771,28 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
       Sets variable <replaceable>varname</> to an integer value calculated
       from <replaceable>expression</>.
       The expression may contain integer constants such as <literal>5432</>,
-      references to variables <literal>:</><replaceable>variablename</>,
+      double constants such as <literal>3.14156</>,
+      references to integer variables <literal>:</><replaceable>variablename</>,
       and expressions composed of unary (<literal>-</>) or binary operators
-      (<literal>+</>, <literal>-</>, <literal>*</>, <literal>/</>, <literal>%</>)
-      with their usual associativity, and parentheses.
+      (<literal>+</>, <literal>-</>, <literal>*</>, <literal>/</>,
+      <literal>%</>) with their usual associativity, function calls and
+      parentheses.
+      <xref linkend="functions-pgbench-func-table"> shows the available
+      functions.
      </para>
 
      <para>
       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>
 
    <varlistentry>
     <term>
-     <literal>\setrandom <replaceable>varname</> <replaceable>min</> <replaceable>max</> [ uniform | { gaussian | exponential } <replaceable>threshold</> ]</literal>
+     <literal>\setrandom <replaceable>varname</> <replaceable>min</> <replaceable>max</> [ uniform | { gaussian | exponential } <replaceable>param</> ]</literal>
      </term>
 
     <listitem>
@@ -801,57 +805,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 threshold 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>-threshold</> on the left and <literal>+threshold</>
-      on the right.
-      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</>, then value <replaceable>i</>
-      between <replaceable>min</> and <replaceable>max</> inclusive is drawn
-      with probability:
-      <literal>
-        (PHI(2.0 * threshold * (i - min - mu + 0.5) / (max - min + 1)) -
-         PHI(2.0 * threshold * (i - min - mu - 0.5) / (max - min + 1))) /
-         (2.0 * PHI(threshold) - 1.0)</>.
-      Intuitively, the larger the <replaceable>threshold</>, 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 / threshold</>
-      and 95% in the middle <literal>2.0 / threshold</>; for instance, if
-      <replaceable>threshold</> is 4.0, 67% of values are drawn from the middle
-      quarter and 95% from the middle half of the interval.
-      The minimum <replaceable>threshold</> 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, the <replaceable>threshold</>
-      parameter controls the distribution by truncating a quickly-decreasing
-      exponential distribution at <replaceable>threshold</>, and then
-      projecting onto integers between the bounds.
-      To be precise, value <replaceable>i</> between <replaceable>min</> and
-      <replaceable>max</> inclusive is drawn with probability:
-      <literal>(exp(-threshold*(i-min)/(max+1-min)) -
-       exp(-threshold*(i+1-min)/(max+1-min))) / (1.0 - exp(-threshold))</>.
-      Intuitively, the larger the <replaceable>threshold</>, 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 the threshold, 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>threshold</>%  of the time.
-      The <replaceable>threshold</> 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>
@@ -931,18 +913,189 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
    </varlistentry>
   </variablelist>
 
+   <!-- list pgbench functions in alphabetical order -->
+   <table id="functions-pgbench-func-table">
+    <title>PgBench Functions</title>
+    <tgroup cols="5">
+     <thead>
+      <row>
+       <entry>Function</entry>
+       <entry>Return Type</entry>
+       <entry>Description</entry>
+       <entry>Example</entry>
+       <entry>Result</entry>
+      </row>
+     </thead>
+     <tbody>
+      <row>
+       <entry><literal><function>abs(<replaceable>a</>)</></></>
+       <entry>same as <replaceable>a</></>
+       <entry>integer or double absolute value</>
+       <entry><literal>abs(-17)</></>
+       <entry><literal>17</></>
+      </row>
+      <row>
+       <entry><literal><function>debug(<replaceable>a</>)</></></>
+       <entry>same as<replaceable>a</> </>
+       <entry>stderr print for debug and return argument</>
+       <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>...</>)</></></>
+       <entry>integer</>
+       <entry>maximum value</>
+       <entry><literal>max(5, 4, 3, 2)</></>
+       <entry><literal>5</></>
+      </row>
+      <row>
+       <entry><literal><function>min(<replaceable>i</>, <replaceable>...</>)</></></>
+       <entry>integer</>
+       <entry>minimum value</>
+       <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 int between <literal>1</> and <literal>10</></>
+      </row>
+      <row>
+       <entry><literal><function>random_exponential(<replaceable>lb</>, <replaceable>ub</>, <replaceable>param</>)</></></>
+       <entry>integer</>
+       <entry>exponentially distributed random integer in <literal>[ub,lb]</>,
+              see below</>
+       <entry><literal>random_exponential(1, 10, 3.0)</></>
+       <entry>an int between <literal>1</> and <literal>10</></>
+      </row>
+      <row>
+       <entry><literal><function>random_gaussian(<replaceable>lb</>, <replaceable>ub</>, <replaceable>param</>)</></></>
+       <entry>integer</>
+       <entry>gaussian distributed random integer in <literal>[ub,lb]</>,
+              see below</>
+       <entry><literal>random_gaussian(1, 10, 2.5)</></>
+       <entry>an int 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 generated values are uniform, that is
+    all values in the specified range are drawn with equal probability.
+   </para>
+
+   <para>
+     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, the <replaceable>param</> parameter
+      controls the distribution by truncating a quickly-decreasing
+      exponential distribution at <replaceable>param</>, and then
+      projecting onto integers between the bounds.
+      To be precise, with
+<literallayout>
+f(x) = exp(-param * (x-min) / (max-min+1)) / (1 - exp(-param))
+</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>param</>, 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 the 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>param</>%  of the time.
+      The <replaceable>param</> 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>-param</> on the left and <literal>+param</>
+      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</>, with
+<literallayout>
+f(x) = PHI(2 * param * (x-mu) / (max-min+1)) / (2 * PHI(param) - 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)</>.
+     </para>
+     <para>
+      Intuitively, the larger the <replaceable>param</>, 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/param</>,
+      that is a relative <literal>0.5/param</> around the mean,
+      and 95% in the middle <literal>2/param</>, that is
+      a relative <literal>1/param</> around the mean;
+      for instance, if <replaceable>param</> is 4.0, 67% of values are drawn
+      from the middle quarter (1/4.0) of the interval
+      (i.e. from <literal>3/8</> to <literal>5/8</>)
+      and 95% from the middle half (2/4.0) of the interval (second and third
+      quartiles).
+      The minimum <replaceable>param</> 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 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
+\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;
@@ -1097,27 +1250,26 @@ starting vacuum...end.
 transaction type: TPC-B (sort of)
 scaling factor: 1
 query mode: simple
-number of clients: 10
+number of clients: 4
 number of threads: 1
-number of transactions per client: 1000
-number of transactions actually processed: 10000/10000
-tps = 618.764555 (including connections establishing)
-tps = 622.977698 (excluding connections establishing)
+duration: 3 s
+number of transactions actually processed: 1239
+latency average: 9.584 ms
+latency stddev: 5.204 ms
+tps = 411.913509 (including connections establishing)
+tps = 413.088125 (excluding connections establishing)
 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.326152        BEGIN;
-        0.603376        UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
-        0.454643        SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
-        5.528491        UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
-        7.335435        UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
-        0.371851        INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
-        1.212976        END;
+        0.010948        \set aid random(1, 100000 * :scale)
+        0.003161        \set bid random(1, 1 * :scale)
+        0.002203        \set tid random(1, 10 * :scale)
+        0.002266        \set delta random(-5000, 5000)
+        0.144510        BEGIN;
+        0.498513        UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
+        0.334889        SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
+        1.436523        UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
+        4.914786        UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
+        0.338837        INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
+        1.877755        END;
 </screen>
   </para>
 
diff --git a/src/bin/pgbench/exprparse.y b/src/bin/pgbench/exprparse.y
index e68631e..51f053f 100644
--- a/src/bin/pgbench/exprparse.y
+++ b/src/bin/pgbench/exprparse.y
@@ -16,10 +16,14 @@
 
 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(char operator, PgBenchExpr *lexpr,
 		PgBenchExpr *rexpr);
+static int find_func(const char * fname);
+static PgBenchExpr *make_func(const int fnumber, PgBenchExprList *args);
 
 %}
 
@@ -29,15 +33,19 @@ static PgBenchExpr *make_op(char operator, PgBenchExpr *lexpr,
 %union
 {
 	int64		ival;
+	double		dval;
 	char	   *str;
 	PgBenchExpr *expr;
+	PgBenchExprList *elist;
 }
 
+%type <elist> elist
 %type <expr> expr
-%type <ival> INTEGER
-%type <str> VARIABLE
+%type <ival> INTEGER function
+%type <dval> DOUBLE
+%type <str> VARIABLE FUNCTION
 
-%token INTEGER VARIABLE
+%token INTEGER DOUBLE VARIABLE FUNCTION
 %token CHAR_ERROR /* never used, will raise a syntax error */
 
 /* Precedence: lowest to highest */
@@ -49,6 +57,11 @@ static PgBenchExpr *make_op(char operator, PgBenchExpr *lexpr,
 
 result: expr				{ expr_parse_result = $1; }
 
+elist:                  	{ $$ = NULL; }
+	| expr 					{ $$ = make_elist($1, NULL); }
+	| elist ',' expr		{ $$ = make_elist($3, $1); }
+	;
+
 expr: '(' expr ')'			{ $$ = $2; }
 	| '+' expr %prec UMINUS	{ $$ = $2; }
 	| '-' expr %prec UMINUS	{ $$ = make_op('-', make_integer_constant(0), $2); }
@@ -58,7 +71,12 @@ expr: '(' expr ')'			{ $$ = $2; }
 	| expr '/' expr			{ $$ = make_op('/', $1, $3); }
 	| expr '%' expr			{ $$ = make_op('%', $1, $3); }
 	| INTEGER				{ $$ = make_integer_constant($1); }
+	| DOUBLE				{ $$ = make_double_constant($1); }
 	| VARIABLE 				{ $$ = make_variable($1); }
+	| function '(' elist ')'{ $$ = make_func($1, $3); }
+	;
+
+function: FUNCTION			{ $$ = find_func($1); pg_free($1); }
 	;
 
 %%
@@ -74,6 +92,16 @@ make_integer_constant(int64 ival)
 }
 
 static PgBenchExpr *
+make_double_constant(double dval)
+{
+	PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
+
+	expr->etype = ENODE_DOUBLE_CONSTANT;
+	expr->u.double_constant.dval = dval;
+	return expr;
+}
+
+static PgBenchExpr *
 make_variable(char *varname)
 {
 	PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
@@ -95,4 +123,122 @@ make_op(char operator, PgBenchExpr *lexpr, PgBenchExpr *rexpr)
 	return expr;
 }
 
+/* list of available functions
+ * - fname: function name
+ * - nargs: number of arguments (-1 is a special value for min & max)
+ * - tag: function identifier from PgBenchFunction enum
+ */
+static struct {
+	char * fname;
+	int nargs;
+	PgBenchFunction tag;
+} PGBENCH_FUNCTIONS[] = {
+	{ "pi", 0, PGBENCH_PI },
+	{ "abs", 1, PGBENCH_ABS },
+	{ "sqrt", 1, PGBENCH_SQRT },
+	{ "int", 1, PGBENCH_INT },
+	{ "double", 1, PGBENCH_DOUBLE },
+	{ "min", -1, PGBENCH_MIN },
+	{ "max", -1, PGBENCH_MAX },
+	{ "random", 2, PGBENCH_RANDOM },
+	{ "random_gaussian", 3, PGBENCH_RANDOM_GAUSSIAN },
+	{ "random_exponential", 3, PGBENCH_RANDOM_EXPONENTIAL },
+	{ "debug", 1, PGBENCH_DEBUG },
+
+	/* keep as last array element */
+	{ NULL, 0, 0 }
+};
+
+/*
+ * Find a function from its name
+ *
+ * return the index of the function from the PGBENCH_FUNCTIONS array
+ * or fail if the function is unknown.
+ */
+static int
+find_func(const char * fname)
+{
+	int i = 0;
+
+	while (PGBENCH_FUNCTIONS[i].fname)
+	{
+		if (pg_strcasecmp(fname, PGBENCH_FUNCTIONS[i].fname) == 0)
+			return i;
+		i++;
+	}
+
+	expr_yyerror_more("unexpected function name", fname);
+
+	/* not reached */
+	return -1;
+}
+
+/* Expression linked list builder */
+static PgBenchExprList *
+make_elist(PgBenchExpr *expr, PgBenchExprList *list)
+{
+	PgBenchExprList *cons = pg_malloc(sizeof(PgBenchExprList));
+	cons->expr = expr;
+	cons->next = list;
+	return cons;
+}
+
+/*
+ * Reverse expression linked list
+ *
+ * The list of function arguments is built in reverse order, and reversed once
+ * at the end so as to avoid appending repeatedly at the end of the list.
+ */
+static PgBenchExprList *
+reverse_elist(PgBenchExprList *list)
+{
+	PgBenchExprList *cur = list, *prec = NULL, *next = NULL;
+
+	while (cur != NULL)
+	{
+		next = cur->next;
+		cur->next = prec;
+		prec = cur;
+		cur = next;
+	}
+
+	return prec;
+}
+
+/* Return the length of an expression list */
+static int
+elist_length(PgBenchExprList *list)
+{
+	int len = 0;
+
+	for (; list != NULL; list = list->next)
+		len++;
+
+	return len;
+}
+
+/* Build function call expression */
+static PgBenchExpr *
+make_func(const int fnumber, PgBenchExprList *args)
+{
+	PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
+
+	Assert(fnumber >= 0);
+
+	if ((PGBENCH_FUNCTIONS[fnumber].nargs >= 0 &&
+		 PGBENCH_FUNCTIONS[fnumber].nargs != elist_length(args)) ||
+		/* check at least one arg for min & max */
+		(PGBENCH_FUNCTIONS[fnumber].nargs == -1 &&
+		 elist_length(args) == 0))
+		expr_yyerror_more("unexpected number of arguments",
+						  PGBENCH_FUNCTIONS[fnumber].fname);
+
+	expr->etype = ENODE_FUNCTION;
+	expr->u.function.function = PGBENCH_FUNCTIONS[fnumber].tag;
+	/* the argument list has been built in reverse order, it is fixed here */
+	expr->u.function.args = reverse_elist(args);
+
+	return expr;
+}
+
 #include "exprscan.c"
diff --git a/src/bin/pgbench/exprscan.l b/src/bin/pgbench/exprscan.l
index 5331ab7..1f8fc65 100644
--- a/src/bin/pgbench/exprscan.l
+++ b/src/bin/pgbench/exprscan.l
@@ -46,6 +46,7 @@ space			[ \t\r\f]
 "%"				{ yycol += yyleng; return '%'; }
 "("				{ yycol += yyleng; return '('; }
 ")"				{ yycol += yyleng; return ')'; }
+","				{ yycol += yyleng; return ','; }
 
 :[a-zA-Z0-9_]+	{
 					yycol += yyleng;
@@ -57,8 +58,19 @@ space			[ \t\r\f]
 					yylval.ival = strtoint64(yytext);
 					return INTEGER;
 				}
+[0-9]+\.[0-9]+	{
+					yycol += yyleng;
+					yylval.dval = atof(yytext);
+					return DOUBLE;
+				}
+[a-zA-Z0-9_]+   {
+					yycol += yyleng;
+					yylval.str = pg_strdup(yytext);
+					return FUNCTION;
+				}
+
+[\n]			{ yycol = 0; yyline++; /* never occurs, input on one line */ }
 
-[\n]			{ yycol = 0; yyline++; }
 {space}+		{ yycol += yyleng; /* ignore */ }
 
 .				{
@@ -71,10 +83,16 @@ space			[ \t\r\f]
 %%
 
 void
-yyerror(const char *message)
+expr_yyerror_more(const char *message, const char *more)
 {
 	syntax_error(expr_source, expr_lineno, expr_full_line, expr_command,
-				 message, NULL, expr_col + yycol);
+				 message, more, expr_col + yycol);
+}
+
+void
+yyerror(const char *message)
+{
+	expr_yyerror_more(message, NULL);
 }
 
 /*
@@ -94,15 +112,14 @@ expr_scanner_init(const char *str, const char *source,
 	expr_command = (char *) cmd;
 	expr_col = (int) ecol;
 
-	/*
-	 * Might be left over after error
-	 */
+	/* reset column count for this scan */
+	yycol = 0;
+
+	/* Might be left over after error */
 	if (YY_CURRENT_BUFFER)
 		yy_delete_buffer(YY_CURRENT_BUFFER);
 
-	/*
-	 * Make a scan buffer with special termination needed by flex.
-	 */
+	/* Make a scan buffer with special termination needed by flex. */
 	scanbuflen = slen;
 	scanbuf = pg_malloc(slen + 2);
 	memcpy(scanbuf, str, slen);
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index f2d435b..47ba244 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -90,7 +90,7 @@ static int	pthread_join(pthread_t th, void **thread_return);
 #define LOG_STEP_SECONDS	5	/* seconds between log messages */
 #define DEFAULT_NXACTS	10		/* default nxacts */
 
-#define MIN_GAUSSIAN_THRESHOLD		2.0 /* minimum threshold for gauss */
+#define MIN_GAUSSIAN_PARAM		2.0 /* minimum parameter for gauss */
 
 int			nxacts = 0;			/* number of transactions per client */
 int			duration = 0;		/* duration in seconds */
@@ -303,13 +303,10 @@ static int	debug = 0;			/* debug flag */
 
 /* default scenario */
 static char *tpc_b = {
-	"\\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"
@@ -321,13 +318,10 @@ static char *tpc_b = {
 
 /* -N case */
 static char *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"
@@ -337,11 +331,22 @@ static char *simple_update = {
 
 /* -S case */
 static char *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"
 };
 
+/* expression evaluation
+ */
+typedef enum { is_none, is_int, is_double } value_type_t;
+
+typedef struct {
+	value_type_t type;
+	union {
+		int64_t ival;
+		double dval;
+	} u;
+} value_t;
+
 /* Function prototypes */
 static void setalarm(int seconds);
 static void *threadRun(void *arg);
@@ -488,47 +493,47 @@ getrand(TState *thread, int64 min, int64 max)
 
 /*
  * random number generator: exponential distribution from min to max inclusive.
- * the threshold is so that the density of probability for the last cut-off max
- * value is exp(-threshold).
+ * the parameter is so that the density of probability for the last cut-off max
+ * value is exp(-param).
  */
 static int64
-getExponentialRand(TState *thread, int64 min, int64 max, double threshold)
+getExponentialRand(TState *thread, int64 min, int64 max, double param)
 {
 	double		cut,
 				uniform,
 				rand;
 
-	Assert(threshold > 0.0);
-	cut = exp(-threshold);
+	Assert(param > 0.0);
+	cut = exp(-param);
 	/* erand in [0, 1), uniform in (0, 1] */
 	uniform = 1.0 - pg_erand48(thread->random_state);
 
 	/*
-	 * inner expresion in (cut, 1] (if threshold > 0), rand in [0, 1)
+	 * inner expresion in (cut, 1] (if param > 0), rand in [0, 1)
 	 */
 	Assert((1.0 - cut) != 0.0);
-	rand = -log(cut + (1.0 - cut) * uniform) / threshold;
+	rand = -log(cut + (1.0 - cut) * uniform) / param;
 	/* return int64 random number within between min and max */
 	return min + (int64) ((max - min + 1) * rand);
 }
 
 /* random number generator: gaussian distribution from min to max inclusive */
 static int64
-getGaussianRand(TState *thread, int64 min, int64 max, double threshold)
+getGaussianRand(TState *thread, int64 min, int64 max, double param)
 {
 	double		stdev;
 	double		rand;
 
 	/*
-	 * Get user specified random number from this loop, with -threshold <
-	 * stdev <= threshold
+	 * Get user specified random number from this loop,
+	 * with -param < stdev <= param
 	 *
 	 * This loop is executed until the number is in the expected range.
 	 *
-	 * As the minimum threshold is 2.0, the probability of looping is low:
+	 * As the minimum parameter is 2.0, the probability of looping is low:
 	 * sqrt(-2 ln(r)) <= 2 => r >= e^{-2} ~ 0.135, then when taking the
 	 * average sinus multiplier as 2/pi, we have a 8.6% looping probability in
-	 * the worst case. For a 5.0 threshold value, the looping probability is
+	 * the worst case. For a 5.0 param value, the looping probability is
 	 * about e^{-5} * 2 / pi ~ 0.43%.
 	 */
 	do
@@ -553,10 +558,10 @@ getGaussianRand(TState *thread, int64 min, int64 max, double threshold)
 		 * over.
 		 */
 	}
-	while (stdev < -threshold || stdev >= threshold);
+	while (stdev < -param || stdev >= param);
 
-	/* stdev is in [-threshold, threshold), normalization to [0,1) */
-	rand = (stdev + threshold) / (threshold * 2.0);
+	/* stdev is in [-param, param), normalization to [0,1) */
+	rand = (stdev + param) / (param * 2.0);
 
 	/* return int64 random number within between min and max */
 	return min + (int64) ((max - min + 1) * rand);
@@ -887,23 +892,295 @@ getQueryParams(CState *st, const Command *command, const char **params)
 }
 
 /*
+ * Recursive evaluation of expressions
+ *
+ * Note that currently only integer variables are available, with values
+ * stored as text.
+ *
+ * CAUTION: do not mix SET_ macros with evaluating on the same value structure.
+ */
+static int
+value_type_error(value_type_t t)
+{
+	fprintf(stderr, "unexpected value type %d\n", t);
+	exit(1);
+	return 0;
+}
+
+#define INT(v)										\
+	(((v).type == is_int)? (v).u.ival:				\
+	 ((v).type == is_double)? (int64_t) (v).u.dval:	\
+	 value_type_error((v).type))
+
+#define DOUBLE(v)								\
+	(((v).type == is_double)? (v).u.dval:		\
+	 ((v).type == is_int)? (double) (v).u.ival:	\
+	 value_type_error((v).type))
+
+#define SET_INT(v, val)						\
+	(v).type = is_int,						\
+		(v).u.ival = (int64_t) val
+
+#define SET_DOUBLE(v, val)				   	\
+	(v).type = is_double,					\
+		(v).u.dval = (double) val
+
+/*
  * Recursive evaluation of an expression in a pgbench script
  * using the current state of variables.
  * Returns whether the evaluation was ok,
  * 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, value_t *retval)
 {
 	switch (expr->etype)
 	{
-		case ENODE_INTEGER_CONSTANT:
+		case ENODE_DOUBLE_CONSTANT:
+		{
+			SET_DOUBLE(*retval, expr->u.double_constant.dval);
+			return true;
+		}
+		case ENODE_OPERATOR:
+		{
+			value_t		lval, rval;
+
+			if (!evaluateExpr(thread, st, expr->u.operator.lexpr, &lval))
+				return false;
+
+			if (!evaluateExpr(thread, st, expr->u.operator.rexpr, &rval))
+				return false;
+
+			/* overloaded type management */
+			if (lval.type == is_double || rval.type == is_double)
+			{
+				switch (expr->u.operator.operator)
+				{
+					case '+':
+						SET_DOUBLE(*retval, DOUBLE(lval) + DOUBLE(rval));
+						return true;
+
+					case '-':
+						SET_DOUBLE(*retval, DOUBLE(lval) - DOUBLE(rval));
+						return true;
+
+					case '*':
+						SET_DOUBLE(*retval, DOUBLE(lval) * DOUBLE(rval));
+						return true;
+
+					case '/':
+						SET_DOUBLE(*retval, DOUBLE(lval) / DOUBLE(rval));
+						return true;
+
+					case '%': /* no overloading for modulo */
+						SET_INT(*retval, INT(lval) % INT(rval));
+						return true;
+				}
+			}
+			else /* both operands are integers */
+			{
+				switch (expr->u.operator.operator)
+				{
+					case '+':
+						SET_INT(*retval, INT(lval) + INT(rval));
+						return true;
+
+					case '-':
+						SET_INT(*retval, INT(lval) - INT(rval));
+						return true;
+
+					case '*':
+						SET_INT(*retval, INT(lval) * INT(rval));
+						return true;
+
+					case '/':
+						SET_INT(*retval, INT(lval) / INT(rval));
+						return true;
+
+					case '%':
+						SET_INT(*retval, INT(lval) % INT(rval));
+						return true;
+				}
+
+			}
+
+			fprintf(stderr, "unexpected operator '%c'\n",
+					expr->u.operator.operator);
+			exit(1);
+		}
+		case ENODE_FUNCTION:
+		{
+			PgBenchFunction func = expr->u.function.function;
+			PgBenchExprList *args = expr->u.function.args;
+
+			switch (func)
+			{
+			case PGBENCH_PI:
+				SET_DOUBLE(*retval, M_PI);
+				return true;
+			case PGBENCH_ABS:
+			{
+				value_t arg;
+
+				if (!evaluateExpr(thread, st, args->expr, &arg))
+					return false;
+
+				if (arg.type == is_double)
+				{
+					if (DOUBLE(arg) < 0.0)
+						SET_DOUBLE(*retval, - DOUBLE(arg));
+					else
+						*retval = arg;
+				}
+				else if (arg.type == is_int)
+				{
+					if (INT(arg) < 0)
+						SET_INT(*retval, - INT(arg));
+					else
+						*retval = arg;
+				}
+
+				return true;
+			}
+			case PGBENCH_SQRT:
+			{
+				value_t arg;
+
+				if (!evaluateExpr(thread, st, args->expr, &arg))
+					return false;
+
+				SET_DOUBLE(*retval, sqrt(DOUBLE(arg)));
+
+				return true;
+			}
+			case PGBENCH_DEBUG:
+			{
+				if (!evaluateExpr(thread, st, args->expr, retval))
+					return false;
+
+				fprintf(stderr,	"debug(script=%d,command=%d): ",
+						st->use_file, st->state+1);
+
+				if (retval->type == is_int)
+					fprintf(stderr,	"int " INT64_FORMAT "\n", retval->u.ival);
+				else if (retval->type == is_double)
+					fprintf(stderr, "double %f\n", retval->u.dval);
+				else
+					fprintf(stderr, "none\n");
+
+				return true;
+			}
+			case PGBENCH_DOUBLE:
 			{
-				*retval = expr->u.integer_constant.ival;
+				value_t arg;
+
+				if (!evaluateExpr(thread, st, args->expr, &arg))
+					return false;
+
+				SET_DOUBLE(*retval, DOUBLE(arg));
+
 				return true;
 			}
+			case PGBENCH_INT:
+			{
+				value_t arg;
+
+				if (!evaluateExpr(thread, st, args->expr, &arg))
+					return false;
+
+				SET_INT(*retval, INT(arg));
+
+				return true;
+			}
+			case PGBENCH_MIN:
+			case PGBENCH_MAX:
+			{
+				int64 val = -1;
+				bool first = true;
+				while (args != NULL)
+				{
+					value_t arg;
+
+					if (!evaluateExpr(thread, st, args->expr, &arg))
+						return false;
+
+					if (first)
+						val = INT(arg);
+					else if (func == PGBENCH_MIN)
+						val = val < INT(arg)? val: INT(arg);
+					else if (func == PGBENCH_MAX)
+						val = val > INT(arg)? val: INT(arg);
 
-		case ENODE_VARIABLE:
+					args = args->next;
+					first = false;
+				}
+
+				SET_INT(*retval, val);
+				return true;
+			}
+
+			case PGBENCH_RANDOM:
+			case PGBENCH_RANDOM_EXPONENTIAL:
+			case PGBENCH_RANDOM_GAUSSIAN:
+			{
+				value_t varg1, varg2;
+				int64_t arg1, arg2;
+
+				if (!evaluateExpr(thread, st, args->expr, &varg1))
+					return false;
+
+				if (!evaluateExpr(thread, st, args->next->expr, &varg2))
+					return false;
+
+				arg1 = INT(varg1);
+				arg2 = INT(varg2);
+
+				/* check random range */
+				if (arg1 > arg2)
+				{
+					fprintf(stderr, "empty range given to random\n");
+					st->ecnt++;
+					return false;
+				}
+				else if (arg2 - arg1 < 0 || (arg2 - arg1) + 1 < 0)
+				{
+					/* prevent int overflows in random functions */
+					fprintf(stderr, "random range is too large\n");
+					st->ecnt++;
+					return false;
+				}
+
+				if (func == PGBENCH_RANDOM)
+					SET_INT(*retval, getrand(thread, arg1, arg2));
+				else /* gaussian & exponential */
+				{
+					value_t param;
+
+					if (!evaluateExpr(thread, st, args->next->next->expr,
+									  &param))
+						return false;
+
+					if (func == PGBENCH_RANDOM_GAUSSIAN)
+						SET_INT(*retval,
+								getGaussianRand(thread, arg1, arg2,
+												DOUBLE(param)));
+					else /* exponential */
+						SET_INT(*retval,
+								getExponentialRand(thread, arg1, arg2,
+												   DOUBLE(param)));
+				}
+
+				return true;
+			}
+			default:
+				fprintf(stderr, "unexpected function tag: %d\n", func);
+				exit(1);
+			}
+		}
+	case ENODE_INTEGER_CONSTANT:
+		SET_INT(*retval, expr->u.integer_constant.ival);
+		return true;
+	case ENODE_VARIABLE:
 			{
 				char	   *var;
 
@@ -913,58 +1190,14 @@ evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval)
 							expr->u.variable.varname);
 					return false;
 				}
-				*retval = strtoint64(var);
+
+				SET_INT(*retval, strtoint64(var));
 				return true;
 			}
-
-		case ENODE_OPERATOR:
-			{
-				int64		lval;
-				int64		rval;
-
-				if (!evaluateExpr(st, expr->u.operator.lexpr, &lval))
-					return false;
-				if (!evaluateExpr(st, expr->u.operator.rexpr, &rval))
-					return false;
-				switch (expr->u.operator.operator)
-				{
-					case '+':
-						*retval = lval + rval;
-						return true;
-
-					case '-':
-						*retval = lval - rval;
-						return true;
-
-					case '*':
-						*retval = lval * rval;
-						return true;
-
-					case '/':
-						if (rval == 0)
-						{
-							fprintf(stderr, "division by zero\n");
-							return false;
-						}
-						*retval = lval / rval;
-						return true;
-
-					case '%':
-						if (rval == 0)
-						{
-							fprintf(stderr, "division by zero\n");
-							return false;
-						}
-						*retval = lval % rval;
-						return true;
-				}
-
-				fprintf(stderr, "bad operator\n");
-				return false;
-			}
-
 		default:
-			break;
+			fprintf(stderr, "unexpected enode type in evaluation: %d\n",
+					expr->etype);
+			exit(1);
 	}
 
 	fprintf(stderr, "bad expression\n");
@@ -1483,7 +1716,7 @@ top:
 			char	   *var;
 			int64		min,
 						max;
-			double		threshold = 0;
+			double		param = 0;
 			char		res[64];
 
 			if (*argv[2] == ':')
@@ -1554,41 +1787,41 @@ top:
 				{
 					if ((var = getVariable(st, argv[5] + 1)) == NULL)
 					{
-						fprintf(stderr, "%s: invalid threshold number: \"%s\"\n",
+						fprintf(stderr, "%s: invalid parameter: \"%s\"\n",
 								argv[0], argv[5]);
 						st->ecnt++;
 						return true;
 					}
-					threshold = strtod(var, NULL);
+					param = strtod(var, NULL);
 				}
 				else
-					threshold = strtod(argv[5], NULL);
+					param = strtod(argv[5], NULL);
 
 				if (pg_strcasecmp(argv[4], "gaussian") == 0)
 				{
-					if (threshold < MIN_GAUSSIAN_THRESHOLD)
+					if (param < MIN_GAUSSIAN_PARAM)
 					{
-						fprintf(stderr, "gaussian threshold must be at least %f (not \"%s\")\n", MIN_GAUSSIAN_THRESHOLD, argv[5]);
+						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, threshold));
+					printf("min: " INT64_FORMAT " max: " INT64_FORMAT " random: " INT64_FORMAT "\n", min, max, getGaussianRand(thread, min, max, param));
 #endif
-					snprintf(res, sizeof(res), INT64_FORMAT, getGaussianRand(thread, min, max, threshold));
+					snprintf(res, sizeof(res), INT64_FORMAT, getGaussianRand(thread, min, max, param));
 				}
 				else if (pg_strcasecmp(argv[4], "exponential") == 0)
 				{
-					if (threshold <= 0.0)
+					if (param <= 0.0)
 					{
-						fprintf(stderr, "exponential threshold must be greater than zero (not \"%s\")\n", argv[5]);
+						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, threshold));
+					printf("min: " INT64_FORMAT " max: " INT64_FORMAT " random: " INT64_FORMAT "\n", min, max, getExponentialRand(thread, min, max, param));
 #endif
-					snprintf(res, sizeof(res), INT64_FORMAT, getExponentialRand(thread, min, max, threshold));
+					snprintf(res, sizeof(res), INT64_FORMAT, getExponentialRand(thread, min, max, param));
 				}
 			}
 			else	/* this means an error somewhere in the parsing phase... */
@@ -1611,14 +1844,14 @@ top:
 		{
 			char		res[64];
 			PgBenchExpr *expr = commands[st->state]->expr;
-			int64		result;
+			value_t		result;
 
-			if (!evaluateExpr(st, expr, &result))
+			if (!evaluateExpr(thread, st, expr, &result))
 			{
 				st->ecnt++;
 				return true;
 			}
-			sprintf(res, INT64_FORMAT, result);
+			sprintf(res, INT64_FORMAT, INT(result));
 
 			if (!putVariable(st, argv[0], argv[1], res))
 			{
@@ -2283,7 +2516,7 @@ process_commands(char *buf, const char *source, const int lineno)
 		{
 			/*
 			 * parsing: \setrandom variable min max [uniform] \setrandom
-			 * variable min max (gaussian|exponential) threshold
+			 * variable min max (gaussian|exponential) parameter
 			 */
 
 			if (my_commands->argc < 4)
@@ -2308,7 +2541,7 @@ process_commands(char *buf, const char *source, const int lineno)
 				if (my_commands->argc < 6)
 				{
 					syntax_error(source, lineno, my_commands->line, my_commands->argv[0],
-					 "missing threshold argument", my_commands->argv[4], -1);
+					 "missing parameter", my_commands->argv[4], -1);
 				}
 				else if (my_commands->argc > 6)
 				{
diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h
index 42e2aae..a293d08 100644
--- a/src/bin/pgbench/pgbench.h
+++ b/src/bin/pgbench/pgbench.h
@@ -14,11 +14,30 @@
 typedef enum PgBenchExprType
 {
 	ENODE_INTEGER_CONSTANT,
+	ENODE_DOUBLE_CONSTANT,
 	ENODE_VARIABLE,
-	ENODE_OPERATOR
+	ENODE_OPERATOR,
+	ENODE_FUNCTION
 } PgBenchExprType;
 
+typedef enum PgBenchFunction
+{
+	PGBENCH_NONE,
+	PGBENCH_PI,
+	PGBENCH_INT,
+	PGBENCH_DOUBLE,
+	PGBENCH_DEBUG,
+	PGBENCH_ABS,
+	PGBENCH_SQRT,
+	PGBENCH_MIN,
+	PGBENCH_MAX,
+	PGBENCH_RANDOM,
+	PGBENCH_RANDOM_GAUSSIAN,
+	PGBENCH_RANDOM_EXPONENTIAL
+} PgBenchFunction;
+
 typedef struct PgBenchExpr PgBenchExpr;
+typedef struct PgBenchExprList PgBenchExprList;
 
 struct PgBenchExpr
 {
@@ -31,6 +50,10 @@ struct PgBenchExpr
 		}			integer_constant;
 		struct
 		{
+			double		dval;
+		}			double_constant;
+		struct
+		{
 			char	   *varname;
 		}			variable;
 		struct
@@ -39,14 +62,25 @@ struct PgBenchExpr
 			PgBenchExpr *lexpr;
 			PgBenchExpr *rexpr;
 		}			operator;
+		struct
+		{
+			PgBenchFunction function;
+			PgBenchExprList *args;
+		}			function;
 	}			u;
 };
 
+struct PgBenchExprList {
+	PgBenchExpr *expr;
+	PgBenchExprList *next;
+};
+
 extern PgBenchExpr *expr_parse_result;
 
 extern int	expr_yyparse(void);
 extern int	expr_yylex(void);
 extern void expr_yyerror(const char *str);
+extern void expr_yyerror_more(const char *str, const char *more);
 extern void expr_scanner_init(const char *str, const char *source,
 				  const int lineno, const char *line,
 				  const char *cmd, const int ecol);

Attachment: functions.sql
Description: application/sql

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