2015-03-02 20:21:41 +01:00
|
|
|
%{
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* exprparse.y
|
|
|
|
* bison grammar for a simple expression syntax
|
|
|
|
*
|
2019-01-02 18:44:25 +01:00
|
|
|
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
2015-03-02 20:21:41 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
2016-03-19 21:35:41 +01:00
|
|
|
* src/bin/pgbench/exprparse.y
|
|
|
|
*
|
2015-03-02 20:21:41 +01:00
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "postgres_fe.h"
|
|
|
|
|
|
|
|
#include "pgbench.h"
|
|
|
|
|
2018-03-21 16:01:23 +01:00
|
|
|
#define PGBENCH_NARGS_VARIABLE (-1)
|
|
|
|
#define PGBENCH_NARGS_CASE (-2)
|
|
|
|
#define PGBENCH_NARGS_HASH (-3)
|
|
|
|
|
2015-03-02 20:21:41 +01:00
|
|
|
PgBenchExpr *expr_parse_result;
|
|
|
|
|
2016-03-01 19:04:09 +01:00
|
|
|
static PgBenchExprList *make_elist(PgBenchExpr *exp, PgBenchExprList *list);
|
2018-01-09 16:02:04 +01:00
|
|
|
static PgBenchExpr *make_null_constant(void);
|
|
|
|
static PgBenchExpr *make_boolean_constant(bool bval);
|
2015-03-02 20:21:41 +01:00
|
|
|
static PgBenchExpr *make_integer_constant(int64 ival);
|
2016-03-29 02:45:57 +02:00
|
|
|
static PgBenchExpr *make_double_constant(double dval);
|
2015-03-02 20:21:41 +01:00
|
|
|
static PgBenchExpr *make_variable(char *varname);
|
2016-03-19 21:35:41 +01:00
|
|
|
static PgBenchExpr *make_op(yyscan_t yyscanner, const char *operator,
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
PgBenchExpr *lexpr, PgBenchExpr *rexpr);
|
2018-01-09 16:02:04 +01:00
|
|
|
static PgBenchExpr *make_uop(yyscan_t yyscanner, const char *operator, PgBenchExpr *expr);
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
static int find_func(yyscan_t yyscanner, const char *fname);
|
2016-03-19 21:35:41 +01:00
|
|
|
static PgBenchExpr *make_func(yyscan_t yyscanner, int fnumber, PgBenchExprList *args);
|
2018-01-09 16:02:04 +01:00
|
|
|
static PgBenchExpr *make_case(yyscan_t yyscanner, PgBenchExprList *when_then_list, PgBenchExpr *else_part);
|
2015-03-02 20:21:41 +01:00
|
|
|
|
|
|
|
%}
|
|
|
|
|
2016-03-21 02:59:03 +01:00
|
|
|
%pure-parser
|
2015-03-02 20:21:41 +01:00
|
|
|
%expect 0
|
|
|
|
%name-prefix="expr_yy"
|
|
|
|
|
2016-03-19 21:35:41 +01:00
|
|
|
%parse-param {yyscan_t yyscanner}
|
|
|
|
%lex-param {yyscan_t yyscanner}
|
|
|
|
|
2015-03-02 20:21:41 +01:00
|
|
|
%union
|
|
|
|
{
|
|
|
|
int64 ival;
|
2016-03-29 02:45:57 +02:00
|
|
|
double dval;
|
2018-01-09 16:02:04 +01:00
|
|
|
bool bval;
|
2015-03-02 20:21:41 +01:00
|
|
|
char *str;
|
|
|
|
PgBenchExpr *expr;
|
2016-03-01 19:04:09 +01:00
|
|
|
PgBenchExprList *elist;
|
2015-03-02 20:21:41 +01:00
|
|
|
}
|
|
|
|
|
2018-01-09 16:02:04 +01:00
|
|
|
%type <elist> elist when_then_list
|
|
|
|
%type <expr> expr case_control
|
2016-03-29 06:53:53 +02:00
|
|
|
%type <ival> INTEGER_CONST function
|
|
|
|
%type <dval> DOUBLE_CONST
|
2018-01-09 16:02:04 +01:00
|
|
|
%type <bval> BOOLEAN_CONST
|
2016-03-01 19:04:09 +01:00
|
|
|
%type <str> VARIABLE FUNCTION
|
2015-03-29 19:06:59 +02:00
|
|
|
|
2018-09-28 06:48:47 +02:00
|
|
|
%token NULL_CONST INTEGER_CONST MAXINT_PLUS_ONE_CONST DOUBLE_CONST
|
|
|
|
%token BOOLEAN_CONST VARIABLE FUNCTION
|
2018-01-09 16:02:04 +01:00
|
|
|
%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
|
|
|
|
|
|
|
|
/* Precedence: lowest to highest, taken from postgres SQL parser */
|
|
|
|
%left OR_OP
|
|
|
|
%left AND_OP
|
|
|
|
%right NOT_OP
|
|
|
|
%nonassoc IS_OP ISNULL_OP NOTNULL_OP
|
|
|
|
%nonassoc '<' '>' '=' LE_OP GE_OP NE_OP
|
|
|
|
%left '|' '#' '&' LS_OP RS_OP '~'
|
2015-03-02 20:21:41 +01:00
|
|
|
%left '+' '-'
|
|
|
|
%left '*' '/' '%'
|
2018-01-09 16:02:04 +01:00
|
|
|
%right UNARY
|
2015-03-02 20:21:41 +01:00
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
result: expr { expr_parse_result = $1; }
|
|
|
|
|
2018-01-09 16:02:04 +01:00
|
|
|
elist: { $$ = NULL; }
|
|
|
|
| expr { $$ = make_elist($1, NULL); }
|
2016-03-01 19:04:09 +01:00
|
|
|
| elist ',' expr { $$ = make_elist($3, $1); }
|
|
|
|
;
|
|
|
|
|
2015-03-02 20:21:41 +01:00
|
|
|
expr: '(' expr ')' { $$ = $2; }
|
2018-01-09 16:02:04 +01:00
|
|
|
| '+' expr %prec UNARY { $$ = $2; }
|
|
|
|
/* unary minus "-x" implemented as "0 - x" */
|
|
|
|
| '-' expr %prec UNARY { $$ = make_op(yyscanner, "-",
|
2016-03-19 21:35:41 +01:00
|
|
|
make_integer_constant(0), $2); }
|
2018-09-28 06:48:47 +02:00
|
|
|
/* special PG_INT64_MIN handling, only after a unary minus */
|
|
|
|
| '-' MAXINT_PLUS_ONE_CONST %prec UNARY
|
|
|
|
{ $$ = make_integer_constant(PG_INT64_MIN); }
|
2018-01-09 16:02:04 +01:00
|
|
|
/* binary ones complement "~x" implemented as 0xffff... xor x" */
|
|
|
|
| '~' expr { $$ = make_op(yyscanner, "#",
|
|
|
|
make_integer_constant(~INT64CONST(0)), $2); }
|
|
|
|
| NOT_OP expr { $$ = make_uop(yyscanner, "!not", $2); }
|
2016-03-19 21:35:41 +01:00
|
|
|
| expr '+' expr { $$ = make_op(yyscanner, "+", $1, $3); }
|
|
|
|
| expr '-' expr { $$ = make_op(yyscanner, "-", $1, $3); }
|
|
|
|
| expr '*' expr { $$ = make_op(yyscanner, "*", $1, $3); }
|
|
|
|
| expr '/' expr { $$ = make_op(yyscanner, "/", $1, $3); }
|
2018-01-09 16:02:04 +01:00
|
|
|
| expr '%' expr { $$ = make_op(yyscanner, "mod", $1, $3); }
|
|
|
|
| expr '<' expr { $$ = make_op(yyscanner, "<", $1, $3); }
|
|
|
|
| expr LE_OP expr { $$ = make_op(yyscanner, "<=", $1, $3); }
|
|
|
|
| expr '>' expr { $$ = make_op(yyscanner, "<", $3, $1); }
|
|
|
|
| expr GE_OP expr { $$ = make_op(yyscanner, "<=", $3, $1); }
|
|
|
|
| expr '=' expr { $$ = make_op(yyscanner, "=", $1, $3); }
|
|
|
|
| expr NE_OP expr { $$ = make_op(yyscanner, "<>", $1, $3); }
|
|
|
|
| expr '&' expr { $$ = make_op(yyscanner, "&", $1, $3); }
|
|
|
|
| expr '|' expr { $$ = make_op(yyscanner, "|", $1, $3); }
|
|
|
|
| expr '#' expr { $$ = make_op(yyscanner, "#", $1, $3); }
|
|
|
|
| expr LS_OP expr { $$ = make_op(yyscanner, "<<", $1, $3); }
|
|
|
|
| expr RS_OP expr { $$ = make_op(yyscanner, ">>", $1, $3); }
|
|
|
|
| expr AND_OP expr { $$ = make_op(yyscanner, "!and", $1, $3); }
|
|
|
|
| expr OR_OP expr { $$ = make_op(yyscanner, "!or", $1, $3); }
|
|
|
|
/* IS variants */
|
|
|
|
| expr ISNULL_OP { $$ = make_op(yyscanner, "!is", $1, make_null_constant()); }
|
|
|
|
| expr NOTNULL_OP {
|
|
|
|
$$ = make_uop(yyscanner, "!not",
|
|
|
|
make_op(yyscanner, "!is", $1, make_null_constant()));
|
|
|
|
}
|
|
|
|
| expr IS_OP NULL_CONST { $$ = make_op(yyscanner, "!is", $1, make_null_constant()); }
|
|
|
|
| expr IS_OP NOT_OP NULL_CONST
|
|
|
|
{
|
|
|
|
$$ = make_uop(yyscanner, "!not",
|
|
|
|
make_op(yyscanner, "!is", $1, make_null_constant()));
|
|
|
|
}
|
|
|
|
| expr IS_OP BOOLEAN_CONST
|
|
|
|
{
|
|
|
|
$$ = make_op(yyscanner, "!is", $1, make_boolean_constant($3));
|
|
|
|
}
|
|
|
|
| expr IS_OP NOT_OP BOOLEAN_CONST
|
|
|
|
{
|
|
|
|
$$ = make_uop(yyscanner, "!not",
|
|
|
|
make_op(yyscanner, "!is", $1, make_boolean_constant($4)));
|
|
|
|
}
|
|
|
|
/* constants */
|
|
|
|
| NULL_CONST { $$ = make_null_constant(); }
|
|
|
|
| BOOLEAN_CONST { $$ = make_boolean_constant($1); }
|
2016-03-29 06:53:53 +02:00
|
|
|
| INTEGER_CONST { $$ = make_integer_constant($1); }
|
|
|
|
| DOUBLE_CONST { $$ = make_double_constant($1); }
|
2018-01-09 16:02:04 +01:00
|
|
|
/* misc */
|
|
|
|
| VARIABLE { $$ = make_variable($1); }
|
2016-03-19 21:35:41 +01:00
|
|
|
| function '(' elist ')' { $$ = make_func(yyscanner, $1, $3); }
|
2018-01-09 16:02:04 +01:00
|
|
|
| case_control { $$ = $1; }
|
2016-03-01 19:04:09 +01:00
|
|
|
;
|
|
|
|
|
2018-01-09 16:02:04 +01:00
|
|
|
when_then_list:
|
|
|
|
when_then_list WHEN_KW expr THEN_KW expr { $$ = make_elist($5, make_elist($3, $1)); }
|
|
|
|
| WHEN_KW expr THEN_KW expr { $$ = make_elist($4, make_elist($2, NULL)); }
|
|
|
|
|
|
|
|
case_control:
|
|
|
|
CASE_KW when_then_list END_KW { $$ = make_case(yyscanner, $2, make_null_constant()); }
|
|
|
|
| CASE_KW when_then_list ELSE_KW expr END_KW { $$ = make_case(yyscanner, $2, $4); }
|
|
|
|
|
2016-03-19 21:35:41 +01:00
|
|
|
function: FUNCTION { $$ = find_func(yyscanner, $1); pg_free($1); }
|
2015-03-02 20:21:41 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
2018-01-09 16:02:04 +01:00
|
|
|
static PgBenchExpr *
|
|
|
|
make_null_constant(void)
|
|
|
|
{
|
|
|
|
PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
|
|
|
|
|
|
|
|
expr->etype = ENODE_CONSTANT;
|
|
|
|
expr->u.constant.type = PGBT_NULL;
|
|
|
|
expr->u.constant.u.ival = 0;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2015-03-02 20:21:41 +01:00
|
|
|
static PgBenchExpr *
|
|
|
|
make_integer_constant(int64 ival)
|
|
|
|
{
|
|
|
|
PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
|
|
|
|
|
2016-03-29 02:45:57 +02:00
|
|
|
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;
|
2015-03-02 20:21:41 +01:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-09 16:02:04 +01:00
|
|
|
static PgBenchExpr *
|
|
|
|
make_boolean_constant(bool bval)
|
|
|
|
{
|
|
|
|
PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
|
|
|
|
|
|
|
|
expr->etype = ENODE_CONSTANT;
|
|
|
|
expr->u.constant.type = PGBT_BOOLEAN;
|
|
|
|
expr->u.constant.u.bval = bval;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2015-03-02 20:21:41 +01:00
|
|
|
static PgBenchExpr *
|
|
|
|
make_variable(char *varname)
|
|
|
|
{
|
|
|
|
PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
|
|
|
|
|
|
|
|
expr->etype = ENODE_VARIABLE;
|
|
|
|
expr->u.variable.varname = varname;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-09 16:02:04 +01:00
|
|
|
/* binary operators */
|
2015-03-02 20:21:41 +01:00
|
|
|
static PgBenchExpr *
|
2016-03-19 21:35:41 +01:00
|
|
|
make_op(yyscan_t yyscanner, const char *operator,
|
|
|
|
PgBenchExpr *lexpr, PgBenchExpr *rexpr)
|
2016-03-01 19:04:09 +01:00
|
|
|
{
|
2016-03-19 21:35:41 +01:00
|
|
|
return make_func(yyscanner, find_func(yyscanner, operator),
|
2016-03-01 19:04:09 +01:00
|
|
|
make_elist(rexpr, make_elist(lexpr, NULL)));
|
|
|
|
}
|
|
|
|
|
2018-01-09 16:02:04 +01:00
|
|
|
/* unary operator */
|
|
|
|
static PgBenchExpr *
|
|
|
|
make_uop(yyscan_t yyscanner, const char *operator, PgBenchExpr *expr)
|
|
|
|
{
|
|
|
|
return make_func(yyscanner, find_func(yyscanner, operator), make_elist(expr, NULL));
|
|
|
|
}
|
|
|
|
|
2016-03-01 19:04:09 +01:00
|
|
|
/*
|
|
|
|
* List of available functions:
|
2018-01-09 16:02:04 +01:00
|
|
|
* - fname: function name, "!..." for special internal functions
|
2018-03-21 16:01:23 +01:00
|
|
|
* - nargs: number of arguments. Special cases:
|
|
|
|
* - PGBENCH_NARGS_VARIABLE is a special value for least & greatest
|
|
|
|
* meaning #args >= 1;
|
|
|
|
* - PGBENCH_NARGS_CASE is for the "CASE WHEN ..." function, which
|
|
|
|
* has #args >= 3 and odd;
|
|
|
|
* - PGBENCH_NARGS_HASH is for hash functions, which have one required
|
|
|
|
* and one optional argument;
|
2016-03-01 19:04:09 +01:00
|
|
|
* - tag: function identifier from PgBenchFunction enum
|
|
|
|
*/
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
static const struct
|
2016-03-01 19:04:09 +01:00
|
|
|
{
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
const char *fname;
|
|
|
|
int nargs;
|
2016-03-01 19:04:09 +01:00
|
|
|
PgBenchFunction tag;
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
} PGBENCH_FUNCTIONS[] =
|
|
|
|
{
|
2016-03-01 19:04:09 +01:00
|
|
|
/* parsed as operators, executed as functions */
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
{
|
|
|
|
"+", 2, PGBENCH_ADD
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"-", 2, PGBENCH_SUB
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"*", 2, PGBENCH_MUL
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"/", 2, PGBENCH_DIV
|
|
|
|
},
|
|
|
|
{
|
2018-01-09 16:02:04 +01:00
|
|
|
"mod", 2, PGBENCH_MOD
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
},
|
2016-03-01 19:04:09 +01:00
|
|
|
/* actual functions */
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
{
|
|
|
|
"abs", 1, PGBENCH_ABS
|
|
|
|
},
|
|
|
|
{
|
2018-03-21 16:01:23 +01:00
|
|
|
"least", PGBENCH_NARGS_VARIABLE, PGBENCH_LEAST
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
},
|
|
|
|
{
|
2018-03-21 16:01:23 +01:00
|
|
|
"greatest", PGBENCH_NARGS_VARIABLE, PGBENCH_GREATEST
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"debug", 1, PGBENCH_DEBUG
|
|
|
|
},
|
2016-03-29 02:45:57 +02:00
|
|
|
{
|
|
|
|
"pi", 0, PGBENCH_PI
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"sqrt", 1, PGBENCH_SQRT
|
|
|
|
},
|
2018-01-09 16:02:04 +01:00
|
|
|
{
|
|
|
|
"ln", 1, PGBENCH_LN
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"exp", 1, PGBENCH_EXP
|
|
|
|
},
|
2016-03-29 02:45:57 +02:00
|
|
|
{
|
|
|
|
"int", 1, PGBENCH_INT
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"double", 1, PGBENCH_DOUBLE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"random", 2, PGBENCH_RANDOM
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"random_gaussian", 3, PGBENCH_RANDOM_GAUSSIAN
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"random_exponential", 3, PGBENCH_RANDOM_EXPONENTIAL
|
|
|
|
},
|
2017-12-14 12:30:22 +01:00
|
|
|
{
|
|
|
|
"random_zipfian", 3, PGBENCH_RANDOM_ZIPFIAN
|
|
|
|
},
|
2017-12-27 19:24:33 +01:00
|
|
|
{
|
|
|
|
"pow", 2, PGBENCH_POW
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"power", 2, PGBENCH_POW
|
|
|
|
},
|
2018-01-09 16:02:04 +01:00
|
|
|
/* logical operators */
|
|
|
|
{
|
|
|
|
"!and", 2, PGBENCH_AND
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"!or", 2, PGBENCH_OR
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"!not", 1, PGBENCH_NOT
|
|
|
|
},
|
|
|
|
/* bitwise integer operators */
|
|
|
|
{
|
|
|
|
"&", 2, PGBENCH_BITAND
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"|", 2, PGBENCH_BITOR
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"#", 2, PGBENCH_BITXOR
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"<<", 2, PGBENCH_LSHIFT
|
|
|
|
},
|
|
|
|
{
|
|
|
|
">>", 2, PGBENCH_RSHIFT
|
|
|
|
},
|
|
|
|
/* comparison operators */
|
|
|
|
{
|
|
|
|
"=", 2, PGBENCH_EQ
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"<>", 2, PGBENCH_NE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"<=", 2, PGBENCH_LE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"<", 2, PGBENCH_LT
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"!is", 2, PGBENCH_IS
|
|
|
|
},
|
|
|
|
/* "case when ... then ... else ... end" construction */
|
|
|
|
{
|
2018-03-21 16:01:23 +01:00
|
|
|
"!case_end", PGBENCH_NARGS_CASE, PGBENCH_CASE
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"hash", PGBENCH_NARGS_HASH, PGBENCH_HASH_MURMUR2
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"hash_murmur2", PGBENCH_NARGS_HASH, PGBENCH_HASH_MURMUR2
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"hash_fnv1a", PGBENCH_NARGS_HASH, PGBENCH_HASH_FNV1A
|
|
|
|
},
|
2016-03-01 19:04:09 +01:00
|
|
|
/* keep as last array element */
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
{
|
|
|
|
NULL, 0, 0
|
|
|
|
}
|
2016-03-01 19:04:09 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
2016-03-19 21:35:41 +01:00
|
|
|
find_func(yyscan_t yyscanner, const char *fname)
|
2016-03-01 19:04:09 +01:00
|
|
|
{
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
int i = 0;
|
2016-03-01 19:04:09 +01:00
|
|
|
|
|
|
|
while (PGBENCH_FUNCTIONS[i].fname)
|
|
|
|
{
|
|
|
|
if (pg_strcasecmp(fname, PGBENCH_FUNCTIONS[i].fname) == 0)
|
|
|
|
return i;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2016-03-19 21:35:41 +01:00
|
|
|
expr_yyerror_more(yyscanner, "unexpected function name", fname);
|
2016-03-01 19:04:09 +01:00
|
|
|
|
|
|
|
/* not reached */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Expression linked list builder */
|
|
|
|
static PgBenchExprList *
|
|
|
|
make_elist(PgBenchExpr *expr, PgBenchExprList *list)
|
|
|
|
{
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
PgBenchExprLink *cons;
|
2016-03-01 19:04:09 +01:00
|
|
|
|
|
|
|
if (list == NULL)
|
|
|
|
{
|
|
|
|
list = pg_malloc(sizeof(PgBenchExprList));
|
|
|
|
list->head = NULL;
|
|
|
|
list->tail = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cons = pg_malloc(sizeof(PgBenchExprLink));
|
|
|
|
cons->expr = expr;
|
|
|
|
cons->next = NULL;
|
|
|
|
|
|
|
|
if (list->head == NULL)
|
|
|
|
list->head = cons;
|
|
|
|
else
|
|
|
|
list->tail->next = cons;
|
|
|
|
|
|
|
|
list->tail = cons;
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the length of an expression list */
|
|
|
|
static int
|
|
|
|
elist_length(PgBenchExprList *list)
|
|
|
|
{
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
PgBenchExprLink *link = list != NULL ? list->head : NULL;
|
|
|
|
int len = 0;
|
2016-03-01 19:04:09 +01:00
|
|
|
|
|
|
|
for (; link != NULL; link = link->next)
|
|
|
|
len++;
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Build function call expression */
|
|
|
|
static PgBenchExpr *
|
2016-03-19 21:35:41 +01:00
|
|
|
make_func(yyscan_t yyscanner, int fnumber, PgBenchExprList *args)
|
2015-03-02 20:21:41 +01:00
|
|
|
{
|
2018-03-21 16:01:23 +01:00
|
|
|
int len = elist_length(args);
|
|
|
|
|
2015-03-02 20:21:41 +01:00
|
|
|
PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
|
|
|
|
|
2016-03-01 19:04:09 +01:00
|
|
|
Assert(fnumber >= 0);
|
|
|
|
|
2018-03-21 16:01:23 +01:00
|
|
|
/* validate arguments number including few special cases */
|
|
|
|
switch (PGBENCH_FUNCTIONS[fnumber].nargs)
|
|
|
|
{
|
|
|
|
/* check at least one arg for least & greatest */
|
|
|
|
case PGBENCH_NARGS_VARIABLE:
|
|
|
|
if (len == 0)
|
|
|
|
expr_yyerror_more(yyscanner, "at least one argument expected",
|
|
|
|
PGBENCH_FUNCTIONS[fnumber].fname);
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* case (when ... then ...)+ (else ...)? end */
|
|
|
|
case PGBENCH_NARGS_CASE:
|
|
|
|
/* 'else' branch is always present, but could be a NULL-constant */
|
|
|
|
if (len < 3 || len % 2 != 1)
|
|
|
|
expr_yyerror_more(yyscanner,
|
|
|
|
"odd and >= 3 number of arguments expected",
|
|
|
|
"case control structure");
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* hash functions with optional seed argument */
|
|
|
|
case PGBENCH_NARGS_HASH:
|
2018-07-27 06:40:24 +02:00
|
|
|
if (len < 1 || len > 2)
|
2018-03-21 16:01:23 +01:00
|
|
|
expr_yyerror_more(yyscanner, "unexpected number of arguments",
|
|
|
|
PGBENCH_FUNCTIONS[fnumber].fname);
|
|
|
|
|
|
|
|
if (len == 1)
|
|
|
|
{
|
|
|
|
PgBenchExpr *var = make_variable("default_seed");
|
|
|
|
args = make_elist(var, args);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* common case: positive arguments number */
|
|
|
|
default:
|
|
|
|
Assert(PGBENCH_FUNCTIONS[fnumber].nargs >= 0);
|
|
|
|
|
|
|
|
if (PGBENCH_FUNCTIONS[fnumber].nargs != len)
|
|
|
|
expr_yyerror_more(yyscanner, "unexpected number of arguments",
|
|
|
|
PGBENCH_FUNCTIONS[fnumber].fname);
|
2018-01-09 16:02:04 +01:00
|
|
|
}
|
2016-03-01 19:04:09 +01:00
|
|
|
|
|
|
|
expr->etype = ENODE_FUNCTION;
|
|
|
|
expr->u.function.function = PGBENCH_FUNCTIONS[fnumber].tag;
|
|
|
|
|
|
|
|
/* only the link is used, the head/tail is not useful anymore */
|
SQL commands in pgbench scripts are now ended by semicolons, not newlines.
To allow multiline SQL commands in scripts, adopt the same rules psql uses
to decide what is the end of a SQL command, to wit, an unquoted semicolon
not encased in parentheses. Do this by importing the same flex lexer that
psql uses, since coping with stuff like dollar-quoted literals is hard to
get right without going the full nine yards.
This makes use of the infrastructure added in commit 0ea9efbe9ec1bf07 to
support independently-written flex lexers scanning the same PsqlScanState
input-buffer data structure. Since that infrastructure isn't very
friendly to ad-hoc parsing code such as strtok(), improve exprscan.l
so that it can parse either whitespace-separated words or expression
tokens, on demand, and rewrite pgbench.c's backslash-command parsing
code to always use the lexer to fetch tokens.
It's still the case that pgbench backslash commands extend to the end
of the line, no more and no less. That could be changed in a fairly
localized way now, and there was some interest in doing so, but it
seems like material for a separate patch.
In passing, make some marginal cleanups in syntax error reporting,
const-ify a few data structures that could use it, and run some of
this code through pgindent.
I can't tell whether the MSVC build scripts need to be taught explicitly
about the changes here or not, but the buildfarm will soon tell us.
Kyotaro Horiguchi and Tom Lane
2016-03-20 17:58:44 +01:00
|
|
|
expr->u.function.args = args != NULL ? args->head : NULL;
|
2016-03-01 19:04:09 +01:00
|
|
|
if (args)
|
|
|
|
pg_free(args);
|
|
|
|
|
2015-03-02 20:21:41 +01:00
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
2018-01-09 16:02:04 +01:00
|
|
|
static PgBenchExpr *
|
|
|
|
make_case(yyscan_t yyscanner, PgBenchExprList *when_then_list, PgBenchExpr *else_part)
|
|
|
|
{
|
|
|
|
return make_func(yyscanner,
|
|
|
|
find_func(yyscanner, "!case_end"),
|
|
|
|
make_elist(else_part, when_then_list));
|
|
|
|
}
|
|
|
|
|
2016-03-19 21:35:41 +01:00
|
|
|
/*
|
|
|
|
* exprscan.l is compiled as part of exprparse.y. Currently, this is
|
|
|
|
* unavoidable because exprparse does not create a .h file to export
|
|
|
|
* its token symbols. If these files ever grow large enough to be
|
|
|
|
* worth compiling separately, that could be fixed; but for now it
|
|
|
|
* seems like useless complication.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* First, get rid of "#define yyscan_t" from pgbench.h */
|
|
|
|
#undef yyscan_t
|
2016-03-21 02:59:03 +01:00
|
|
|
/* ... and the yylval macro, which flex will have its own definition for */
|
|
|
|
#undef yylval
|
2016-03-19 21:35:41 +01:00
|
|
|
|
2015-03-02 20:21:41 +01:00
|
|
|
#include "exprscan.c"
|