Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit878fdcb

Browse files
committed
pgbench: Add a real expression syntax to \set
Previously, you could do \set variable operand1 operator operand2, butnothing more complicated. Now, you can \set variable expression, whichmakes it much simpler to do multi-step calculations here. This alsoadds support for the modulo operator (%), with the same semantics as inC.Robert Haas and Fabien Coelho, reviewed by Álvaro Herrera andStephen Frost
1 parentebd092b commit878fdcb

File tree

8 files changed

+425
-84
lines changed

8 files changed

+425
-84
lines changed

‎contrib/pgbench/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
/exprparse.c
2+
/exprscan.c
13
/pgbench

‎contrib/pgbench/Makefile

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ PGFILEDESC = "pgbench - a simple program for running benchmark tests"
44
PGAPPICON = win32
55

66
PROGRAM = pgbench
7-
OBJS= pgbench.o$(WIN32RES)
7+
OBJS= pgbench.o exprparse.o$(WIN32RES)
8+
9+
EXTRA_CLEAN= exprparse.c exprscan.c
810

911
PG_CPPFLAGS = -I$(libpq_srcdir)
1012
PG_LIBS =$(libpq_pgport)$(PTHREAD_LIBS)
@@ -18,8 +20,21 @@ subdir = contrib/pgbench
1820
top_builddir = ../..
1921
include$(top_builddir)/src/Makefile.global
2022
include$(top_srcdir)/contrib/contrib-global.mk
23+
24+
distprep: exprparse.c exprscan.c
2125
endif
2226

2327
ifneq ($(PORTNAME), win32)
2428
overrideCFLAGS +=$(PTHREAD_CFLAGS)
2529
endif
30+
31+
# There is no correct way to write a rule that generates two files.
32+
# Rules with two targets don't have that meaning, they are merely
33+
# shorthand for two otherwise separate rules. To be safe for parallel
34+
# make, we must chain the dependencies like this. The semicolon is
35+
# important; otherwise, make will choose the built-in rule.
36+
37+
exprparse.h: exprparse.c ;
38+
39+
# exprscan is compiled as part of exprparse
40+
exprparse.o: exprscan.c

‎contrib/pgbench/exprparse.y

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
%{
2+
/*-------------------------------------------------------------------------
3+
*
4+
* exprparse.y
5+
* bison grammar for a simple expression syntax
6+
*
7+
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
8+
* Portions Copyright (c) 1994, Regents of the University of California
9+
*
10+
*-------------------------------------------------------------------------
11+
*/
12+
13+
#include"postgres_fe.h"
14+
15+
#include"pgbench.h"
16+
17+
PgBenchExpr *expr_parse_result;
18+
19+
static PgBenchExpr *make_integer_constant(int64 ival);
20+
static PgBenchExpr *make_variable(char *varname);
21+
static PgBenchExpr *make_op(charoperator, PgBenchExpr *lexpr,
22+
PgBenchExpr *rexpr);
23+
24+
%}
25+
26+
%expect0
27+
%name-prefix="expr_yy"
28+
29+
%union
30+
{
31+
int64ival;
32+
char *str;
33+
PgBenchExpr *expr;
34+
}
35+
36+
%type<expr>expr
37+
%type<ival>INTEGER
38+
%type<str>VARIABLE
39+
%tokenINTEGERVARIABLE
40+
%tokenCHAR_ERROR/* never used, will raise a syntax error*/
41+
42+
%left'+''-'
43+
%left'*''/''%'
44+
%rightUMINUS
45+
46+
%%
47+
48+
result:expr{ expr_parse_result =$1; }
49+
50+
expr:'('expr')'{$$ =$2; }
51+
|'+'expr %precUMINUS{$$ =$2; }
52+
|'-'expr %precUMINUS{$$ = make_op('-', make_integer_constant(0),$2); }
53+
|expr'+'expr{$$ = make_op('+',$1,$3); }
54+
|expr'-'expr{$$ = make_op('-',$1,$3); }
55+
|expr'*'expr{$$ = make_op('*',$1,$3); }
56+
|expr'/'expr{$$ = make_op('/',$1,$3); }
57+
|expr'%'expr{$$ = make_op('%',$1,$3); }
58+
|INTEGER{$$ = make_integer_constant($1); }
59+
|VARIABLE {$$ = make_variable($1); }
60+
;
61+
62+
%%
63+
64+
static PgBenchExpr *
65+
make_integer_constant(int64 ival)
66+
{
67+
PgBenchExpr *expr =pg_malloc(sizeof(PgBenchExpr));
68+
69+
expr->etype = ENODE_INTEGER_CONSTANT;
70+
expr->u.integer_constant.ival = ival;
71+
return expr;
72+
}
73+
74+
static PgBenchExpr *
75+
make_variable(char *varname)
76+
{
77+
PgBenchExpr *expr =pg_malloc(sizeof(PgBenchExpr));
78+
79+
expr->etype = ENODE_VARIABLE;
80+
expr->u.variable.varname = varname;
81+
return expr;
82+
}
83+
84+
static PgBenchExpr *
85+
make_op(charoperator, PgBenchExpr *lexpr, PgBenchExpr *rexpr)
86+
{
87+
PgBenchExpr *expr =pg_malloc(sizeof(PgBenchExpr));
88+
89+
expr->etype = ENODE_OPERATOR;
90+
expr->u.operator.operator =operator;
91+
expr->u.operator.lexpr = lexpr;
92+
expr->u.operator.rexpr = rexpr;
93+
return expr;
94+
}
95+
96+
#include"exprscan.c"

‎contrib/pgbench/exprscan.l

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
%{
2+
/*-------------------------------------------------------------------------
3+
*
4+
* exprscan.l
5+
* a lexical scanner for a simple expression syntax
6+
*
7+
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
8+
* Portions Copyright (c) 1994, Regents of the University of California
9+
*
10+
*-------------------------------------------------------------------------
11+
*/
12+
13+
/* line and column number for error reporting*/
14+
staticintyyline =0, yycol =0;
15+
16+
/* Handles to the buffer that the lexer uses internally*/
17+
static YY_BUFFER_STATE scanbufhandle;
18+
staticchar *scanbuf;
19+
staticintscanbuflen;
20+
21+
/* flex 2.5.4 doesn't bother with a decl for this*/
22+
intexpr_yylex(void);
23+
24+
%}
25+
26+
%option8bit
27+
%optionnever-interactive
28+
%optionnodefault
29+
%optionnoinput
30+
%optionnounput
31+
%optionnoyywrap
32+
%optionwarn
33+
%optionprefix="expr_yy"
34+
35+
non_newline[^\n\r]
36+
space[\t\r\f]
37+
38+
%%
39+
40+
"+"{ yycol += yyleng;return'+'; }
41+
"-"{ yycol += yyleng;return'-'; }
42+
"*"{ yycol += yyleng;return'*'; }
43+
"/"{ yycol += yyleng;return'/'; }
44+
"%"{ yycol += yyleng;return'%'; }
45+
"("{ yycol += yyleng;return'('; }
46+
")"{ yycol += yyleng;return')'; }
47+
:[a-zA-Z0-9_]+{ yycol += yyleng; yylval.str =pg_strdup(yytext +1);return VARIABLE; }
48+
[0-9]+{ yycol += yyleng; yylval.ival =strtoint64(yytext);return INTEGER; }
49+
50+
[\n]{ yycol =0; yyline++; }
51+
{space}{ yycol += yyleng;/* ignore */ }
52+
53+
.{
54+
yycol += yyleng;
55+
fprintf(stderr,"unexpected character '%s'\n", yytext);
56+
return CHAR_ERROR;
57+
}
58+
%%
59+
60+
void
61+
yyerror(constchar *message)
62+
{
63+
/* yyline is always 1 as pgbench calls the parser for each line...
64+
* so the interesting location information is the column number */
65+
fprintf(stderr,"%s at column %d\n", message, yycol);
66+
/* go on to raise the error from pgbench with more information */
67+
/* exit(1); */
68+
}
69+
70+
/*
71+
* Called before any actual parsing is done
72+
*/
73+
void
74+
expr_scanner_init(constchar *str)
75+
{
76+
Sizeslen =strlen(str);
77+
78+
/*
79+
* Might be left over after error
80+
*/
81+
if (YY_CURRENT_BUFFER)
82+
yy_delete_buffer(YY_CURRENT_BUFFER);
83+
84+
/*
85+
* Make a scan buffer with special termination needed by flex.
86+
*/
87+
scanbuflen = slen;
88+
scanbuf =pg_malloc(slen +2);
89+
memcpy(scanbuf, str, slen);
90+
scanbuf[slen] = scanbuf[slen +1] = YY_END_OF_BUFFER_CHAR;
91+
scanbufhandle =yy_scan_buffer(scanbuf, slen +2);
92+
93+
BEGIN(INITIAL);
94+
}
95+
96+
97+
/*
98+
* Called after parsing is done to clean up after seg_scanner_init()
99+
*/
100+
void
101+
expr_scanner_finish(void)
102+
{
103+
yy_delete_buffer(scanbufhandle);
104+
pg_free(scanbuf);
105+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp