2015-03-02 20:21:41 +01:00
|
|
|
%{
|
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* exprparse.y
|
|
|
|
* bison grammar for a simple expression syntax
|
|
|
|
*
|
2016-01-02 19:33:40 +01:00
|
|
|
* Portions Copyright (c) 1996-2016, 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"
|
|
|
|
|
|
|
|
PgBenchExpr *expr_parse_result;
|
|
|
|
|
2016-03-01 19:04:09 +01:00
|
|
|
static PgBenchExprList *make_elist(PgBenchExpr *exp, PgBenchExprList *list);
|
2015-03-02 20:21:41 +01:00
|
|
|
static PgBenchExpr *make_integer_constant(int64 ival);
|
|
|
|
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);
|
|
|
|
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);
|
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;
|
|
|
|
char *str;
|
|
|
|
PgBenchExpr *expr;
|
2016-03-01 19:04:09 +01:00
|
|
|
PgBenchExprList *elist;
|
2015-03-02 20:21:41 +01:00
|
|
|
}
|
|
|
|
|
2016-03-01 19:04:09 +01:00
|
|
|
%type <elist> elist
|
2015-03-02 20:21:41 +01:00
|
|
|
%type <expr> expr
|
2016-03-01 19:04:09 +01:00
|
|
|
%type <ival> INTEGER function
|
|
|
|
%type <str> VARIABLE FUNCTION
|
2015-03-29 19:06:59 +02:00
|
|
|
|
2016-03-01 19:04:09 +01:00
|
|
|
%token INTEGER VARIABLE FUNCTION
|
2015-03-02 20:21:41 +01:00
|
|
|
|
2015-03-29 19:06:59 +02:00
|
|
|
/* Precedence: lowest to highest */
|
2015-03-02 20:21:41 +01:00
|
|
|
%left '+' '-'
|
|
|
|
%left '*' '/' '%'
|
|
|
|
%right UMINUS
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
result: expr { expr_parse_result = $1; }
|
|
|
|
|
2016-03-01 19:04:09 +01:00
|
|
|
elist: { $$ = NULL; }
|
|
|
|
| expr { $$ = make_elist($1, NULL); }
|
|
|
|
| elist ',' expr { $$ = make_elist($3, $1); }
|
|
|
|
;
|
|
|
|
|
2015-03-02 20:21:41 +01:00
|
|
|
expr: '(' expr ')' { $$ = $2; }
|
|
|
|
| '+' expr %prec UMINUS { $$ = $2; }
|
2016-03-19 21:35:41 +01:00
|
|
|
| '-' expr %prec UMINUS { $$ = make_op(yyscanner, "-",
|
|
|
|
make_integer_constant(0), $2); }
|
|
|
|
| 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); }
|
|
|
|
| expr '%' expr { $$ = make_op(yyscanner, "%", $1, $3); }
|
2015-03-02 20:21:41 +01:00
|
|
|
| INTEGER { $$ = make_integer_constant($1); }
|
|
|
|
| VARIABLE { $$ = make_variable($1); }
|
2016-03-19 21:35:41 +01:00
|
|
|
| function '(' elist ')' { $$ = make_func(yyscanner, $1, $3); }
|
2016-03-01 19:04:09 +01:00
|
|
|
;
|
|
|
|
|
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
|
|
|
;
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
static PgBenchExpr *
|
|
|
|
make_integer_constant(int64 ival)
|
|
|
|
{
|
|
|
|
PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
|
|
|
|
|
|
|
|
expr->etype = ENODE_INTEGER_CONSTANT;
|
|
|
|
expr->u.integer_constant.ival = ival;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PgBenchExpr *
|
|
|
|
make_variable(char *varname)
|
|
|
|
{
|
|
|
|
PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
|
|
|
|
|
|
|
|
expr->etype = ENODE_VARIABLE;
|
|
|
|
expr->u.variable.varname = varname;
|
|
|
|
return expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
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)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* List of available functions:
|
|
|
|
* - fname: function name
|
|
|
|
* - nargs: number of arguments
|
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
|
|
|
* -1 is a special value for min & max meaning #args >= 1
|
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
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"%", 2, PGBENCH_MOD
|
|
|
|
},
|
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
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"min", -1, PGBENCH_MIN
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"max", -1, PGBENCH_MAX
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"debug", 1, PGBENCH_DEBUG
|
|
|
|
},
|
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
|
|
|
{
|
|
|
|
PgBenchExpr *expr = pg_malloc(sizeof(PgBenchExpr));
|
|
|
|
|
2016-03-01 19:04:09 +01:00
|
|
|
Assert(fnumber >= 0);
|
|
|
|
|
|
|
|
if (PGBENCH_FUNCTIONS[fnumber].nargs >= 0 &&
|
|
|
|
PGBENCH_FUNCTIONS[fnumber].nargs != elist_length(args))
|
2016-03-19 21:35:41 +01:00
|
|
|
expr_yyerror_more(yyscanner, "unexpected number of arguments",
|
2016-03-01 19:04:09 +01:00
|
|
|
PGBENCH_FUNCTIONS[fnumber].fname);
|
|
|
|
|
|
|
|
/* check at least one arg for min & max */
|
|
|
|
if (PGBENCH_FUNCTIONS[fnumber].nargs == -1 &&
|
|
|
|
elist_length(args) == 0)
|
2016-03-19 21:35:41 +01:00
|
|
|
expr_yyerror_more(yyscanner, "at least one argument expected",
|
2016-03-01 19:04:09 +01:00
|
|
|
PGBENCH_FUNCTIONS[fnumber].fname);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
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"
|