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 options d integer constants such as 5432, double constants such as 3.14159, references to variables :variablename, + testing whether a variable exists + :{?variablename}, operators with their usual SQL precedence and associativity, function calls, 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 INTEGER_CONST function %type DOUBLE_CONST %type BOOLEAN_CONST -%type VARIABLE FUNCTION +%type 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