Patch v2 is a rebase.

Patch v3 is also a rebase.

--
Fabien.
diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml
index 41d9030..7b3badf 100644
--- a/doc/src/sgml/ref/pgbench.sgml
+++ b/doc/src/sgml/ref/pgbench.sgml
@@ -971,6 +971,8 @@ pgbench <optional> <replaceable>options</replaceable> 
</optional> <replaceable>d
       integer constants such as <literal>5432</literal>,
       double constants such as <literal>3.14159</literal>,
       references to variables 
<literal>:</literal><replaceable>variablename</replaceable>,
+      testing whether a variable exists
+      
<literal>:{?</literal><replaceable>variablename</replaceable><literal>}</literal>,
       <link linkend="pgbench-builtin-operators">operators</link>
       with their usual SQL precedence and associativity,
       <link linkend="pgbench-builtin-functions">function calls</link>,
diff --git a/src/bin/pgbench/exprparse.y b/src/bin/pgbench/exprparse.y
index 8447e14..2f89142 100644
--- a/src/bin/pgbench/exprparse.y
+++ b/src/bin/pgbench/exprparse.y
@@ -28,6 +28,7 @@ static PgBenchExpr *make_boolean_constant(bool bval);
 static PgBenchExpr *make_integer_constant(int64 ival);
 static PgBenchExpr *make_double_constant(double dval);
 static PgBenchExpr *make_variable(char *varname);
+static PgBenchExpr *make_variable_exists(char *varname);
 static PgBenchExpr *make_op(yyscan_t yyscanner, const char *operator,
                PgBenchExpr *lexpr, PgBenchExpr *rexpr);
 static PgBenchExpr *make_uop(yyscan_t yyscanner, const char *operator, 
PgBenchExpr *expr);
@@ -59,9 +60,10 @@ static PgBenchExpr *make_case(yyscan_t yyscanner, 
PgBenchExprList *when_then_lis
 %type <ival> INTEGER_CONST function
 %type <dval> DOUBLE_CONST
 %type <bval> BOOLEAN_CONST
-%type <str> VARIABLE FUNCTION
+%type <str> VARIABLE VAREXISTS FUNCTION
 
-%token NULL_CONST INTEGER_CONST DOUBLE_CONST BOOLEAN_CONST VARIABLE FUNCTION
+%token NULL_CONST INTEGER_CONST DOUBLE_CONST BOOLEAN_CONST
+%token VARIABLE VAREXISTS FUNCTION
 %token AND_OP OR_OP NOT_OP NE_OP LE_OP GE_OP LS_OP RS_OP IS_OP
 %token CASE_KW WHEN_KW THEN_KW ELSE_KW END_KW
 
@@ -140,6 +142,7 @@ expr: '(' expr ')'                  { $$ = $2; }
        | DOUBLE_CONST                  { $$ = make_double_constant($1); }
        /* misc */
        | VARIABLE                              { $$ = make_variable($1); }
+       | VAREXISTS                             { $$ = 
make_variable_exists($1); }
        | function '(' elist ')' { $$ = make_func(yyscanner, $1, $3); }
        | case_control                  { $$ = $1; }
        ;
@@ -213,6 +216,16 @@ make_variable(char *varname)
 
 /* binary operators */
 static PgBenchExpr *
+make_variable_exists(char *varname)
+{
+       PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
+
+       expr->etype = ENODE_VAREXISTS;
+       expr->u.variable.varname = varname;
+       return expr;
+}
+
+static PgBenchExpr *
 make_op(yyscan_t yyscanner, const char *operator,
                PgBenchExpr *lexpr, PgBenchExpr *rexpr)
 {
diff --git a/src/bin/pgbench/exprscan.l b/src/bin/pgbench/exprscan.l
index 5c1bd88..ff2b586 100644
--- a/src/bin/pgbench/exprscan.l
+++ b/src/bin/pgbench/exprscan.l
@@ -191,6 +191,13 @@ notnull                    [Nn][Oo][Tt][Nn][Uu][Ll][Ll]
                                        yylval->bval = false;
                                        return BOOLEAN_CONST;
                                }
+:\{\?{alnum}+\}        {
+                                       /* no pg_strndup? */
+                                       yylval->str = pg_strdup(yytext + 3);
+                                       /* scratch final '}' */
+                                       yylval->str[strlen(yylval->str)-1] = 
'\0';
+                                       return VAREXISTS;
+                               }
 {digit}+               {
                                        yylval->ival = strtoint64(yytext);
                                        return INTEGER_CONST;
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 8529e7d..3ddceffe 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -2360,6 +2360,10 @@ evaluateExpr(TState *thread, CState *st, PgBenchExpr 
*expr, PgBenchValue *retval
                                return true;
                        }
 
+               case ENODE_VAREXISTS:
+                               setBoolValue(retval, lookupVariable(st, 
expr->u.variable.varname) != NULL);
+                               return true;
+
                case ENODE_FUNCTION:
                        return evalFunc(thread, st,
                                                        
expr->u.function.function,
diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h
index 6983865..284443e 100644
--- a/src/bin/pgbench/pgbench.h
+++ b/src/bin/pgbench/pgbench.h
@@ -58,6 +58,7 @@ typedef enum PgBenchExprType
 {
        ENODE_CONSTANT,
        ENODE_VARIABLE,
+       ENODE_VAREXISTS,
        ENODE_FUNCTION
 } PgBenchExprType;
 
diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl 
b/src/bin/pgbench/t/001_pgbench_with_server.pl
index 0929418..f6c2f53 100644
--- a/src/bin/pgbench/t/001_pgbench_with_server.pl
+++ b/src/bin/pgbench/t/001_pgbench_with_server.pl
@@ -283,6 +283,8 @@ pgbench(
                qr{command=96.: int 1\b},    # :scale
                qr{command=97.: int 0\b},    # :client_id
                qr{command=98.: int 5432\b}, # :random_seed
+               qr{command=99.: boolean false\b}, # var exists
+               qr{command=100.: boolean true\b},
        ],
        'pgbench expressions',
        {   '001_pgbench_expressions' => q{-- integer functions
@@ -407,6 +409,9 @@ SELECT :v0, :v1, :v2, :v3;
 \set sc debug(:scale)
 \set ci debug(:client_id)
 \set rs debug(:random_seed)
+-- test variable existence
+\set no debug(:{?no_such_variable})
+\set yes debug(:{?cs})
 } });
 
 # random determinism when seeded

Reply via email to