Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
b54073ea
Commit
b54073ea
authored
24 years ago
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert to standard 4-space tabs.
parent
26608036
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1375 additions
and
1375 deletions
+1375
-1375
src/pl/plpgsql/src/gram.y
src/pl/plpgsql/src/gram.y
+1375
-1375
No files found.
src/pl/plpgsql/src/gram.y
View file @
b54073ea
%{
%{
/**********************************************************************
/**********************************************************************
* gram.y - Parser for the PL/pgSQL
* gram.y
- Parser for the PL/pgSQL
* procedural language
*
procedural language
*
*
* IDENTIFICATION
* IDENTIFICATION
*
$Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.13 2001/01/06 01:39:01 tgl
Exp $
*
$Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.14 2001/02/10 22:42:01 momjian
Exp $
*
*
*
This software is copyrighted by Jan Wieck - Hamburg.
*
This software is copyrighted by Jan Wieck - Hamburg.
*
*
*
The author hereby grants permission to use, copy,
modify,
*
The author hereby grants permission to use, copy,
modify,
*
distribute, and
license this software and its documentation
*
distribute, and
license this software and its documentation
*
for any purpose, provided that existing copyright notices are
*
for any purpose, provided that existing copyright notices are
*
retained in all copies and that
this notice is included
*
retained in all copies and that
this notice is included
*
verbatim in any distributions. No written agreement, license,
*
verbatim in any distributions. No written agreement, license,
*
or royalty fee
is required for any of the authorized uses.
*
or royalty fee
is required for any of the authorized uses.
*
Modifications to this software may be copyrighted by their
*
Modifications to this software may be copyrighted by their
*
author and need not follow the licensing terms described
*
author and need not follow the licensing terms described
*
here, provided that the new terms are clearly indicated on
*
here, provided that the new terms are clearly indicated on
*
the first page of each file where they apply.
*
the first page of each file where they apply.
*
*
*
IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
*
IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
*
PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
OR
*
PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
OR
*
CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OF THIS
*
CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OF THIS
*
SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
*
SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
*
IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
*
IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
*
DAMAGE.
*
DAMAGE.
*
*
*
THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM
ANY
*
THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM
ANY
*
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED
*
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED
*
WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR
*
WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR
*
PURPOSE,
AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
*
PURPOSE,
AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
*
AN "AS IS" BASIS, AND THE AUTHOR
AND DISTRIBUTORS HAVE NO
*
AN "AS IS" BASIS, AND THE AUTHOR
AND DISTRIBUTORS HAVE NO
*
OBLIGATION TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES,
*
OBLIGATION TO PROVIDE MAINTENANCE,
SUPPORT, UPDATES,
*
ENHANCEMENTS, OR MODIFICATIONS.
*
ENHANCEMENTS, OR MODIFICATIONS.
*
*
**********************************************************************/
**********************************************************************/
...
@@ -52,61 +52,61 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
...
@@ -52,61 +52,61 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%}
%}
%union {
%union {
int32
ival;
int32
ival;
char
*str;
char
*str;
struct {
struct {
char *name;
char *name;
int lineno;
int lineno;
}
varname;
}
varname;
struct {
struct {
int nalloc;
int nalloc;
int
nused;
int
nused;
int
*dtnums;
int
*dtnums;
}
dtlist;
}
dtlist;
struct {
struct {
int reverse;
int reverse;
PLpgSQL_expr *expr;
PLpgSQL_expr *expr;
}
forilow;
}
forilow;
struct {
struct {
char *label;
char *label;
int n_initvars;
int n_initvars;
int *initvarnos;
int *initvarnos;
}
declhdr;
}
declhdr;
PLpgSQL_type
*dtype;
PLpgSQL_type
*dtype;
PLpgSQL_var
*var;
PLpgSQL_var
*var;
PLpgSQL_row
*row;
PLpgSQL_row
*row;
PLpgSQL_rec
*rec;
PLpgSQL_rec
*rec;
PLpgSQL_recfield
*recfield;
PLpgSQL_recfield
*recfield;
PLpgSQL_trigarg
*trigarg;
PLpgSQL_trigarg
*trigarg;
PLpgSQL_expr
*expr;
PLpgSQL_expr
*expr;
PLpgSQL_stmt
*stmt;
PLpgSQL_stmt
*stmt;
PLpgSQL_stmts
*stmts;
PLpgSQL_stmts
*stmts;
PLpgSQL_stmt_block
*program;
PLpgSQL_stmt_block
*program;
PLpgSQL_nsitem
*nsitem;
PLpgSQL_nsitem
*nsitem;
}
}
%type <declhdr>
decl_sect
%type <declhdr>
decl_sect
%type <varname>
decl_varname
%type <varname>
decl_varname
%type <str> decl_renname
%type <str>
decl_renname
%type <ival> decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval
%type <ival> decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval
%type <expr> decl_defval
%type <expr> decl_defval
%type <dtype> decl_datatype, decl_dtypename
%type <dtype> decl_datatype, decl_dtypename
%type <row> decl_rowtype
%type <row>
decl_rowtype
%type <nsitem> decl_aliasitem
%type <nsitem> decl_aliasitem
%type <str> decl_stmts, decl_stmt
%type <str>
decl_stmts, decl_stmt
%type <expr> expr_until_semi, expr_until_then, expr_until_loop
%type <expr> expr_until_semi, expr_until_then, expr_until_loop
%type <expr> opt_exitcond
%type <expr> opt_exitcond
%type <ival> assign_var
%type <ival> assign_var
%type <var> fori_var
%type <var>
fori_var
%type <varname>
fori_varname
%type <varname>
fori_varname
%type <forilow>
fori_lower
%type <forilow>
fori_lower
%type <rec> fors_target
%type <rec>
fors_target
%type <str> opt_lblname, opt_label
%type <str>
opt_lblname, opt_label
%type <str> opt_exitlabel
%type <str>
opt_exitlabel
%type <str> execsql_start
%type <str>
execsql_start
%type <stmts> proc_sect, proc_stmts, stmt_else, loop_body
%type <stmts> proc_sect, proc_stmts, stmt_else, loop_body
%type <stmt> proc_stmt, pl_block
%type <stmt> proc_stmt, pl_block
...
@@ -117,16 +117,16 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
...
@@ -117,16 +117,16 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%type <dtlist> raise_params
%type <dtlist> raise_params
%type <ival> raise_level, raise_param
%type <ival> raise_level, raise_param
%type <str> raise_msg
%type <str>
raise_msg
%type <dtlist> getdiag_items, getdiag_targets
%type <dtlist> getdiag_items, getdiag_targets
%type <ival> getdiag_item, getdiag_target
%type <ival> getdiag_item, getdiag_target
%type <ival> lno
%type <ival> lno
/*
/*
* Keyword tokens
* Keyword tokens
*/
*/
%token K_ALIAS
%token K_ALIAS
%token K_ASSIGN
%token K_ASSIGN
%token K_BEGIN
%token K_BEGIN
...
@@ -152,7 +152,7 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
...
@@ -152,7 +152,7 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%token K_NOTICE
%token K_NOTICE
%token K_NULL
%token K_NULL
%token K_PERFORM
%token K_PERFORM
%token
K_PROCESSED
%token
K_PROCESSED
%token K_RAISE
%token K_RAISE
%token K_RECORD
%token K_RECORD
%token K_RENAME
%token K_RENAME
...
@@ -166,9 +166,9 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
...
@@ -166,9 +166,9 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%token K_WHEN
%token K_WHEN
%token K_WHILE
%token K_WHILE
/*
/*
* Other tokens
* Other tokens
*/
*/
%token T_FUNCTION
%token T_FUNCTION
%token T_TRIGGER
%token T_TRIGGER
%token T_CHAR
%token T_CHAR
...
@@ -192,1047 +192,1047 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
...
@@ -192,1047 +192,1047 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%%
%%
pl_function : T_FUNCTION comp_optsect pl_block
pl_function
: T_FUNCTION comp_optsect pl_block
{
{
yylval.program = (PLpgSQL_stmt_block *)$3;
yylval.program = (PLpgSQL_stmt_block *)$3;
}
}
| T_TRIGGER comp_optsect pl_block
| T_TRIGGER comp_optsect pl_block
{
{
yylval.program = (PLpgSQL_stmt_block *)$3;
yylval.program = (PLpgSQL_stmt_block *)$3;
}
}
;
;
comp_optsect :
comp_optsect :
| comp_options
| comp_options
;
;
comp_options : comp_options comp_option
comp_options : comp_options comp_option
| comp_option
| comp_option
;
;
comp_option : O_OPTION O_DUMP
comp_option
: O_OPTION O_DUMP
{
{
plpgsql_DumpExecTree = 1;
plpgsql_DumpExecTree = 1;
}
}
;
;
pl_block : decl_sect K_BEGIN lno proc_sect K_END ';'
pl_block
: decl_sect K_BEGIN lno proc_sect K_END ';'
{
{
PLpgSQL_stmt_block *new;
PLpgSQL_stmt_block *new;
new = malloc(sizeof(PLpgSQL_stmt_block));
new = malloc(sizeof(PLpgSQL_stmt_block));
memset(new, 0, sizeof(PLpgSQL_stmt_block));
memset(new, 0, sizeof(PLpgSQL_stmt_block));
new->cmd_type
= PLPGSQL_STMT_BLOCK;
new->cmd_type
= PLPGSQL_STMT_BLOCK;
new->lineno
= $3;
new->lineno
= $3;
new->label
= $1.label;
new->label
= $1.label;
new->n_initvars = $1.n_initvars;
new->n_initvars = $1.n_initvars;
new->initvarnos = $1.initvarnos;
new->initvarnos = $1.initvarnos;
new->body
= $4;
new->body
= $4;
plpgsql_ns_pop();
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
decl_sect : opt_label
decl_sect
: opt_label
{
{
plpgsql_ns_setlocal(false);
plpgsql_ns_setlocal(false);
$$.label
= $1;
$$.label
= $1;
$$.n_initvars = 0;
$$.n_initvars = 0;
$$.initvarnos = NULL;
$$.initvarnos = NULL;
plpgsql_add_initdatums(NULL);
plpgsql_add_initdatums(NULL);
}
}
| opt_label decl_start
| opt_label decl_start
{
{
plpgsql_ns_setlocal(false);
plpgsql_ns_setlocal(false);
$$.label
= $1;
$$.label
= $1;
$$.n_initvars = 0;
$$.n_initvars = 0;
$$.initvarnos = NULL;
$$.initvarnos = NULL;
plpgsql_add_initdatums(NULL);
plpgsql_add_initdatums(NULL);
}
}
| opt_label decl_start decl_stmts
| opt_label decl_start decl_stmts
{
{
plpgsql_ns_setlocal(false);
plpgsql_ns_setlocal(false);
if ($3 != NULL) {
if ($3 != NULL) {
$$.label = $3;
$$.label = $3;
} else {
} else {
$$.label = $1;
$$.label = $1;
}
}
$$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
$$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
}
}
;
;
decl_start : K_DECLARE
decl_start
: K_DECLARE
{
{
plpgsql_ns_setlocal(true);
plpgsql_ns_setlocal(true);
}
}
;
;
decl_stmts : decl_stmts decl_stmt
decl_stmts
: decl_stmts decl_stmt
{
{
$$ = $2;
$$ = $2;
}
}
| decl_stmt
| decl_stmt
{
{
$$ = $1;
$$ = $1;
}
}
;
;
decl_stmt : '<' '<' opt_lblname '>' '>'
decl_stmt
: '<' '<' opt_lblname '>' '>'
{
{
$$ = $3;
$$ = $3;
}
}
| K_DECLARE
| K_DECLARE
{
{
$$ = NULL;
$$ = NULL;
}
}
| decl_statement
| decl_statement
{
{
$$ = NULL;
$$ = NULL;
}
}
;
;
decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
{
{
PLpgSQL_var
*new;
PLpgSQL_var
*new;
new = malloc(sizeof(PLpgSQL_var));
new = malloc(sizeof(PLpgSQL_var));
new->dtype
= PLPGSQL_DTYPE_VAR;
new->dtype
= PLPGSQL_DTYPE_VAR;
new->refname = $1.name;
new->refname = $1.name;
new->lineno
= $1.lineno;
new->lineno
= $1.lineno;
new->datatype = $3;
new->datatype = $3;
new->isconst = $2;
new->isconst = $2;
new->notnull = $4;
new->notnull = $4;
new->default_val = $5;
new->default_val = $5;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
$1.name);
$1.name);
}
}
| decl_varname K_RECORD ';'
| decl_varname K_RECORD ';'
{
{
PLpgSQL_rec
*new;
PLpgSQL_rec
*new;
new = malloc(sizeof(PLpgSQL_var));
new = malloc(sizeof(PLpgSQL_var));
new->dtype
= PLPGSQL_DTYPE_REC;
new->dtype
= PLPGSQL_DTYPE_REC;
new->refname = $1.name;
new->refname = $1.name;
new->lineno
= $1.lineno;
new->lineno
= $1.lineno;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
$1.name);
$1.name);
}
}
| decl_varname decl_rowtype ';'
| decl_varname decl_rowtype ';'
{
{
$2->dtype
= PLPGSQL_DTYPE_ROW;
$2->dtype
= PLPGSQL_DTYPE_ROW;
$2->refname
= $1.name;
$2->refname
= $1.name;
$2->lineno
= $1.lineno;
$2->lineno
= $1.lineno;
plpgsql_adddatum((PLpgSQL_datum *)$2);
plpgsql_adddatum((PLpgSQL_datum *)$2);
plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
$1.name);
$1.name);
}
}
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
{
{
plpgsql_ns_additem($4->itemtype,
plpgsql_ns_additem($4->itemtype,
$4->itemno, $1.name);
$4->itemno, $1.name);
}
}
| K_RENAME decl_renname K_TO decl_renname ';'
| K_RENAME decl_renname K_TO decl_renname ';'
{
{
plpgsql_ns_rename($2, $4);
plpgsql_ns_rename($2, $4);
}
}
;
;
decl_aliasitem : T_WORD
decl_aliasitem : T_WORD
{
{
PLpgSQL_nsitem *nsi;
PLpgSQL_nsitem *nsi;
char *name;
char *name;
plpgsql_ns_setlocal(false);
plpgsql_ns_setlocal(false);
name = plpgsql_tolower(yytext);
name = plpgsql_tolower(yytext);
if (name[0] != '$') {
if (name[0] != '$') {
elog(ERROR, "can only alias positional parameters");
elog(ERROR, "can only alias positional parameters");
}
}
nsi = plpgsql_ns_lookup(name, NULL);
nsi = plpgsql_ns_lookup(name, NULL);
if (nsi == NULL) {
if (nsi == NULL) {
elog(ERROR, "function has no parameter %s", name);
elog(ERROR, "function has no parameter %s", name);
}
}
plpgsql_ns_setlocal(true);
plpgsql_ns_setlocal(true);
$$ = nsi;
$$ = nsi;
}
}
;
;
decl_rowtype : T_ROW
decl_rowtype : T_ROW
{
{
$$ = yylval.row;
$$ = yylval.row;
}
}
;
;
decl_varname : T_WORD
decl_varname : T_WORD
{
{
/* name should be malloc'd for use as varname */
/* name should be malloc'd for use as varname */
$$.name = strdup(plpgsql_tolower(yytext));
$$.name = strdup(plpgsql_tolower(yytext));
$$.lineno = yylineno;
$$.lineno = yylineno;
}
}
;
;
decl_renname : T_WORD
decl_renname : T_WORD
{
{
/* the result must be palloc'd, see plpgsql_ns_rename */
/* the result must be palloc'd, see plpgsql_ns_rename */
$$ = plpgsql_tolower(yytext);
$$ = plpgsql_tolower(yytext);
}
}
;
;
decl_const :
decl_const
:
{ $$ = 0; }
{ $$ = 0; }
| K_CONSTANT
| K_CONSTANT
{ $$ = 1; }
{ $$ = 1; }
;
;
decl_datatype : decl_dtypename
decl_datatype : decl_dtypename
{
{
$$ = $1;
$$ = $1;
}
}
;
;
decl_dtypename : T_DTYPE
decl_dtypename : T_DTYPE
{
{
$$ = yylval.dtype;
$$ = yylval.dtype;
}
}
| T_CHAR decl_atttypmod
| T_CHAR decl_atttypmod
{
{
if ($2 < 0) {
if ($2 < 0) {
plpgsql_parse_word("char");
plpgsql_parse_word("char");
$$ = yylval.dtype;
$$ = yylval.dtype;
} else {
} else {
plpgsql_parse_word("bpchar");
plpgsql_parse_word("bpchar");
$$ = yylval.dtype;
$$ = yylval.dtype;
$$->atttypmod = $2;
$$->atttypmod = $2;
}
}
}
}
| T_VARCHAR decl_atttypmod
| T_VARCHAR decl_atttypmod
{
{
plpgsql_parse_word("varchar");
plpgsql_parse_word("varchar");
$$ = yylval.dtype;
$$ = yylval.dtype;
$$->atttypmod = $2;
$$->atttypmod = $2;
}
}
| T_BPCHAR '(' decl_atttypmodval ')'
| T_BPCHAR '(' decl_atttypmodval ')'
{
{
plpgsql_parse_word("bpchar");
plpgsql_parse_word("bpchar");
$$ = yylval.dtype;
$$ = yylval.dtype;
$$->atttypmod = $3;
$$->atttypmod = $3;
}
}
;
;
decl_atttypmod :
decl_atttypmod :
{
{
$$ = -1;
$$ = -1;
}
}
| '(' decl_atttypmodval ')'
| '(' decl_atttypmodval ')'
{
{
$$ = $2;
$$ = $2;
}
}
;
;
decl_atttypmodval : T_NUMBER
decl_atttypmodval
: T_NUMBER
{
{
$$ = pg_atoi(yytext, sizeof(int16), '\0') + VARHDRSZ;
$$ = pg_atoi(yytext, sizeof(int16), '\0') + VARHDRSZ;
}
}
;
;
decl_notnull :
decl_notnull :
{ $$ = 0; }
{ $$ = 0; }
| K_NOT K_NULL
| K_NOT K_NULL
{ $$ = 1; }
{ $$ = 1; }
;
;
decl_defval : ';'
decl_defval
: ';'
{ $$ = NULL; }
{ $$ = NULL; }
| decl_defkey
| decl_defkey
{
{
int
tok;
int
tok;
int
lno;
int
lno;
PLpgSQL_dstring
ds;
PLpgSQL_dstring
ds;
PLpgSQL_expr *expr;
PLpgSQL_expr *expr;
lno = yylineno;
lno = yylineno;
expr = malloc(sizeof(PLpgSQL_expr));
expr = malloc(sizeof(PLpgSQL_expr));
plpgsql_dstring_init(&ds);
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
plpgsql_dstring_append(&ds, "SELECT ");
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->plan
= NULL;
expr->plan
= NULL;
expr->nparams = 0;
expr->nparams = 0;
tok = yylex();
tok = yylex();
switch (tok) {
switch (tok) {
case 0:
case 0:
plpgsql_error_lineno = lno;
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "unexpected end of file");
elog(ERROR, "unexpected end of file");
case K_NULL:
case K_NULL:
if (yylex() != ';') {
if (yylex() != ';') {
plpgsql_error_lineno = lno;
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "expectec ; after NULL");
elog(ERROR, "expectec ; after NULL");
}
}
free(expr);
free(expr);
plpgsql_dstring_free(&ds);
plpgsql_dstring_free(&ds);
$$ = NULL;
$$ = NULL;
break;
break;
default:
default:
plpgsql_dstring_append(&ds, yytext);
plpgsql_dstring_append(&ds, yytext);
while ((tok = yylex()) != ';') {
while ((tok = yylex()) != ';') {
if (tok == 0) {
if (tok == 0) {
plpgsql_error_lineno = lno;
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "unterminated default value");
elog(ERROR, "unterminated default value");
}
}
if (plpgsql_SpaceScanned) {
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
plpgsql_dstring_append(&ds, " ");
}
}
plpgsql_dstring_append(&ds, yytext);
plpgsql_dstring_append(&ds, yytext);
}
}
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->query = strdup(plpgsql_dstring_get(&ds));
plpgsql_dstring_free(&ds);
plpgsql_dstring_free(&ds);
$$ = expr;
$$ = expr;
break;
break;
}
}
}
}
;
;
decl_defkey : K_ASSIGN
decl_defkey
: K_ASSIGN
| K_DEFAULT
| K_DEFAULT
proc_sect :
proc_sect
:
{
{
PLpgSQL_stmts *new;
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
$$ = new;
$$ = new;
}
}
| proc_stmts
| proc_stmts
{
{
$$ = $1;
$$ = $1;
}
}
;
;
proc_stmts : proc_stmts proc_stmt
proc_stmts
: proc_stmts proc_stmt
{
{
if ($1->stmts_used == $1->stmts_alloc) {
if ($1->stmts_used == $1->stmts_alloc) {
$1->stmts_alloc *= 2;
$1->stmts_alloc *= 2;
$1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
$1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
}
}
$1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
$1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
$$ = $1;
$$ = $1;
}
}
| proc_stmt
| proc_stmt
{
{
PLpgSQL_stmts *new;
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
new->stmts_alloc = 64;
new->stmts_alloc = 64;
new->stmts_used = 1;
new->stmts_used = 1;
new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
new->stmts[0] = (struct PLpgSQL_stmt *)$1;
new->stmts[0] = (struct PLpgSQL_stmt *)$1;
$$ = new;
$$ = new;
}
}
;
;
proc_stmt : pl_block
proc_stmt
: pl_block
{ $$ = $1; }
{ $$ = $1; }
| stmt_assign
| stmt_assign
{ $$ = $1; }
{ $$ = $1; }
| stmt_if
| stmt_if
{ $$ = $1; }
{ $$ = $1; }
| stmt_loop
| stmt_loop
{ $$ = $1; }
{ $$ = $1; }
| stmt_while
| stmt_while
{ $$ = $1; }
{ $$ = $1; }
| stmt_fori
| stmt_fori
{ $$ = $1; }
{ $$ = $1; }
| stmt_fors
| stmt_fors
{ $$ = $1; }
{ $$ = $1; }
| stmt_select
| stmt_select
{ $$ = $1; }
{ $$ = $1; }
| stmt_exit
| stmt_exit
{ $$ = $1; }
{ $$ = $1; }
| stmt_return
| stmt_return
{ $$ = $1; }
{ $$ = $1; }
| stmt_raise
| stmt_raise
{ $$ = $1; }
{ $$ = $1; }
| stmt_execsql
| stmt_execsql
{ $$ = $1; }
{ $$ = $1; }
| stmt_dynexecute
| stmt_dynexecute
{ $$ = $1; }
{ $$ = $1; }
| stmt_dynfors
| stmt_dynfors
{ $$ = $1; }
{ $$ = $1; }
| stmt_perform
| stmt_perform
{ $$ = $1; }
{ $$ = $1; }
| stmt_getdiag
| stmt_getdiag
{ $$ = $1; }
{ $$ = $1; }
;
;
stmt_perform : K_PERFORM lno expr_until_semi
stmt_perform : K_PERFORM lno expr_until_semi
{
{
PLpgSQL_stmt_assign *new;
PLpgSQL_stmt_assign *new;
new = malloc(sizeof(PLpgSQL_stmt_assign));
new = malloc(sizeof(PLpgSQL_stmt_assign));
memset(new, 0, sizeof(PLpgSQL_stmt_assign));
memset(new, 0, sizeof(PLpgSQL_stmt_assign));
new->cmd_type = PLPGSQL_STMT_ASSIGN;
new->cmd_type = PLPGSQL_STMT_ASSIGN;
new->lineno = $2;
new->lineno = $2;
new->varno = -1;
new->varno = -1;
new->expr = $3;
new->expr = $3;
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
stmt_assign : assign_var lno K_ASSIGN expr_until_semi
stmt_assign
: assign_var lno K_ASSIGN expr_until_semi
{
{
PLpgSQL_stmt_assign *new;
PLpgSQL_stmt_assign *new;
new = malloc(sizeof(PLpgSQL_stmt_assign));
new = malloc(sizeof(PLpgSQL_stmt_assign));
memset(new, 0, sizeof(PLpgSQL_stmt_assign));
memset(new, 0, sizeof(PLpgSQL_stmt_assign));
new->cmd_type = PLPGSQL_STMT_ASSIGN;
new->cmd_type = PLPGSQL_STMT_ASSIGN;
new->lineno = $2;
new->lineno = $2;
new->varno = $1;
new->varno = $1;
new->expr = $4;
new->expr = $4;
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
stmt_getdiag : K_GET K_DIAGNOSTICS lno K_SELECT getdiag_items K_INTO getdiag_targets ';'
stmt_getdiag : K_GET K_DIAGNOSTICS lno K_SELECT getdiag_items K_INTO getdiag_targets ';'
{
{
PLpgSQL_stmt_getdiag
*new;
PLpgSQL_stmt_getdiag
*new;
new = malloc(sizeof(PLpgSQL_stmt_getdiag));
new = malloc(sizeof(PLpgSQL_stmt_getdiag));
memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
new->cmd_type = PLPGSQL_STMT_GETDIAG;
new->cmd_type = PLPGSQL_STMT_GETDIAG;
new->lineno = $3;
new->lineno = $3;
new->nitems = $5.nused;
new->nitems = $5.nused;
new->items
= malloc(sizeof(int) * $5.nused);
new->items
= malloc(sizeof(int) * $5.nused);
new->ntargets = $7.nused;
new->ntargets = $7.nused;
new->targets = malloc(sizeof(int) * $7.nused);
new->targets = malloc(sizeof(int) * $7.nused);
memcpy(new->items, $5.dtnums, sizeof(int) * $5.nused);
memcpy(new->items, $5.dtnums, sizeof(int) * $5.nused);
memcpy(new->targets, $7.dtnums, sizeof(int) * $7.nused);
memcpy(new->targets, $7.dtnums, sizeof(int) * $7.nused);
if (new->nitems != new->ntargets) {
if (new->nitems != new->ntargets) {
plpgsql_error_lineno = new->lineno;
plpgsql_error_lineno = new->lineno;
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "number of diagnostic items does not match target list");
elog(ERROR, "number of diagnostic items does not match target list");
};
};
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
getdiag_items : getdiag_items ',' getdiag_item
getdiag_items : getdiag_items ',' getdiag_item
{
{
if ($1.nused == $1.nalloc) {
if ($1.nused == $1.nalloc) {
$1.nalloc *= 2;
$1.nalloc *= 2;
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
}
}
$1.dtnums[$1.nused++] = $3;
$1.dtnums[$1.nused++] = $3;
$$.nalloc = $1.nalloc;
$$.nalloc = $1.nalloc;
$$.nused = $1.nused;
$$.nused = $1.nused;
$$.dtnums = $1.dtnums;
$$.dtnums = $1.dtnums;
}
}
| getdiag_item
| getdiag_item
{
{
$$.nalloc = 1;
$$.nalloc = 1;
$$.nused = 1;
$$.nused = 1;
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums[0] = $1;
$$.dtnums[0] = $1;
}
}
;
;
getdiag_item : K_PROCESSED
getdiag_item : K_PROCESSED
{
{
$$ = PLPGSQL_GETDIAG_PROCESSED;
$$ = PLPGSQL_GETDIAG_PROCESSED;
}
}
| K_RESULT
| K_RESULT
{
{
$$ = PLPGSQL_GETDIAG_RESULT;
$$ = PLPGSQL_GETDIAG_RESULT;
}
}
;
;
getdiag_targets : getdiag_targets ',' getdiag_target
getdiag_targets : getdiag_targets ',' getdiag_target
{
{
if ($1.nused == $1.nalloc) {
if ($1.nused == $1.nalloc) {
$1.nalloc *= 2;
$1.nalloc *= 2;
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
}
}
$1.dtnums[$1.nused++] = $3;
$1.dtnums[$1.nused++] = $3;
$$.nalloc = $1.nalloc;
$$.nalloc = $1.nalloc;
$$.nused = $1.nused;
$$.nused = $1.nused;
$$.dtnums = $1.dtnums;
$$.dtnums = $1.dtnums;
}
}
| getdiag_target
| getdiag_target
{
{
$$.nalloc = 1;
$$.nalloc = 1;
$$.nused = 1;
$$.nused = 1;
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums[0] = $1;
$$.dtnums[0] = $1;
}
}
;
;
getdiag_target : T_VARIABLE
getdiag_target : T_VARIABLE
{
{
if (yylval.var->isconst) {
if (yylval.var->isconst) {
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname);
elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname);
}
}
$$ = yylval.var->varno;
$$ = yylval.var->varno;
}
}
| T_RECFIELD
| T_RECFIELD
{
{
$$ = yylval.recfield->rfno;
$$ = yylval.recfield->rfno;
}
}
;
;
assign_var : T_VARIABLE
assign_var : T_VARIABLE
{
{
if (yylval.var->isconst) {
if (yylval.var->isconst) {
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
}
}
$$ = yylval.var->varno;
$$ = yylval.var->varno;
}
}
| T_RECFIELD
| T_RECFIELD
{
{
$$ = yylval.recfield->rfno;
$$ = yylval.recfield->rfno;
}
}
;
;
stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
{
{
PLpgSQL_stmt_if *new;
PLpgSQL_stmt_if *new;
new = malloc(sizeof(PLpgSQL_stmt_if));
new = malloc(sizeof(PLpgSQL_stmt_if));
memset(new, 0, sizeof(PLpgSQL_stmt_if));
memset(new, 0, sizeof(PLpgSQL_stmt_if));
new->cmd_type = PLPGSQL_STMT_IF;
new->cmd_type = PLPGSQL_STMT_IF;
new->lineno = $2;
new->lineno = $2;
new->cond = $3;
new->cond = $3;
new->true_body = $4;
new->true_body = $4;
new->false_body = $5;
new->false_body = $5;
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
stmt_else :
stmt_else :
{
{
PLpgSQL_stmts *new;
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
$$ = new;
$$ = new;
}
}
| K_ELSE proc_sect
| K_ELSE proc_sect
{ $$ = $2; }
{ $$ = $2; }
;
;
stmt_loop : opt_label K_LOOP lno loop_body
stmt_loop : opt_label K_LOOP lno loop_body
{
{
PLpgSQL_stmt_loop *new;
PLpgSQL_stmt_loop *new;
new = malloc(sizeof(PLpgSQL_stmt_loop));
new = malloc(sizeof(PLpgSQL_stmt_loop));
memset(new, 0, sizeof(PLpgSQL_stmt_loop));
memset(new, 0, sizeof(PLpgSQL_stmt_loop));
new->cmd_type = PLPGSQL_STMT_LOOP;
new->cmd_type = PLPGSQL_STMT_LOOP;
new->lineno = $3;
new->lineno = $3;
new->label = $1;
new->label = $1;
new->body = $4;
new->body = $4;
plpgsql_ns_pop();
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
{
{
PLpgSQL_stmt_while *new;
PLpgSQL_stmt_while *new;
new = malloc(sizeof(PLpgSQL_stmt_while));
new = malloc(sizeof(PLpgSQL_stmt_while));
memset(new, 0, sizeof(PLpgSQL_stmt_while));
memset(new, 0, sizeof(PLpgSQL_stmt_while));
new->cmd_type = PLPGSQL_STMT_WHILE;
new->cmd_type = PLPGSQL_STMT_WHILE;
new->lineno = $3;
new->lineno = $3;
new->label = $1;
new->label = $1;
new->cond = $4;
new->cond = $4;
new->body = $5;
new->body = $5;
plpgsql_ns_pop();
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
stmt_fori : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
{
PLpgSQL_stmt_fori *new;
new = malloc(sizeof(PLpgSQL_stmt_fori));
memset(new, 0, sizeof(PLpgSQL_stmt_fori));
new->cmd_type = PLPGSQL_STMT_FORI;
new->lineno = $3;
new->label = $1;
new->var = $4;
new->reverse = $6.reverse;
new->lower = $6.expr;
new->upper = $7;
new->body = $8;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
;
fori_var : fori_varname
{
PLpgSQL_var *new;
new = malloc(sizeof(PLpgSQL_var));
stmt_fori : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
new->dtype = PLPGSQL_DTYPE_VAR;
{
new->refname = $1.name;
PLpgSQL_stmt_fori *new
;
new->lineno = $1.lineno
;
new = malloc(sizeof(PLpgSQL_stmt_fori));
plpgsql_parse_word("integer");
memset(new, 0, sizeof(PLpgSQL_stmt_fori));
new->cmd_type = PLPGSQL_STMT_FORI;
new->datatype = yylval.dtype;
new->lineno = $3;
new->isconst = false;
new->label = $1;
new->notnull = false;
new->var = $4;
new->default_val = NULL;
new->reverse = $6.reverse;
new->lower = $6.expr;
new->upper = $7;
new->body = $8;
plpgsql_ns_pop();
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
$1.name);
$$ = (PLpgSQL_stmt *)new;
plpgsql_add_initdatums(NULL);
}
;
fori_var : fori_varname
$$ = new;
{
}
PLpgSQL_var *new;
;
new = malloc(sizeof(PLpgSQL_var));
new->dtype = PLPGSQL_DTYPE_VAR;
new->refname = $1.name;
new->lineno = $1.lineno;
plpgsql_parse_word("integer");
new->datatype = yylval.dtype;
new->isconst = false;
new->notnull = false;
new->default_val = NULL;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
$1.name);
plpgsql_add_initdatums(NULL);
$$ = new;
}
;
fori_varname : T_VARIABLE
fori_varname : T_VARIABLE
{
{
$$.name = strdup(yytext);
$$.name = strdup(yytext);
$$.lineno = yylineno;
$$.lineno = yylineno;
}
}
| T_WORD
| T_WORD
{
{
$$.name = strdup(yytext);
$$.name = strdup(yytext);
$$.lineno = yylineno;
$$.lineno = yylineno;
}
}
;
;
fori_lower :
fori_lower
:
{
{
int
tok;
int
tok;
int
lno;
int
lno;
PLpgSQL_dstring
ds;
PLpgSQL_dstring
ds;
int
nparams = 0;
int
nparams = 0;
int
params[1024];
int
params[1024];
char
buf[32];
char
buf[32];
PLpgSQL_expr *expr;
PLpgSQL_expr *expr;
int
firsttok = 1;
int
firsttok = 1;
lno = yylineno;
lno = yylineno;
plpgsql_dstring_init(&ds);
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
plpgsql_dstring_append(&ds, "SELECT ");
$$.reverse = 0;
$$.reverse = 0;
while((tok = yylex()) != K_DOTDOT) {
while((tok = yylex()) != K_DOTDOT) {
if (firsttok) {
if (firsttok) {
firsttok = 0;
firsttok = 0;
if (tok == K_REVERSE) {
if (tok == K_REVERSE) {
$$.reverse = 1;
$$.reverse = 1;
continue;
continue;
}
}
}
}
if (tok == ';') break;
if (tok == ';') break;
if (plpgsql_SpaceScanned) {
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
plpgsql_dstring_append(&ds, " ");
}
}
switch (tok) {
switch (tok) {
case T_VARIABLE:
case T_VARIABLE:
params[nparams] = yylval.var->varno;
params[nparams] = yylval.var->varno;
sprintf(buf, " $%d ", ++nparams);
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
plpgsql_dstring_append(&ds, buf);
break;
break;
case T_RECFIELD:
case T_RECFIELD:
params[nparams] = yylval.recfield->rfno;
params[nparams] = yylval.recfield->rfno;
sprintf(buf, " $%d ", ++nparams);
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
plpgsql_dstring_append(&ds, buf);
break;
break;
case T_TGARGV:
case T_TGARGV:
params[nparams] = yylval.trigarg->dno;
params[nparams] = yylval.trigarg->dno;
sprintf(buf, " $%d ", ++nparams);
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
plpgsql_dstring_append(&ds, buf);
break;
break;
default:
default:
if (tok == 0) {
if (tok == 0) {
plpgsql_error_lineno = lno;
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "missing .. to terminate lower bound of for loop");
elog(ERROR, "missing .. to terminate lower bound of for loop");
}
}
plpgsql_dstring_append(&ds, yytext);
plpgsql_dstring_append(&ds, yytext);
break;
break;
}
}
}
}
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
expr->dtype
= PLPGSQL_DTYPE_EXPR;
expr->dtype
= PLPGSQL_DTYPE_EXPR;
expr->query
= strdup(plpgsql_dstring_get(&ds));
expr->query
= strdup(plpgsql_dstring_get(&ds));
expr->plan
= NULL;
expr->plan
= NULL;
expr->nparams = nparams;
expr->nparams = nparams;
while(nparams-- > 0) {
while(nparams-- > 0) {
expr->params[nparams] = params[nparams];
expr->params[nparams] = params[nparams];
}
}
plpgsql_dstring_free(&ds);
plpgsql_dstring_free(&ds);
$$.expr = expr;
$$.expr = expr;
}
}
stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
stmt_fors
: opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
{
{
PLpgSQL_stmt_fors
*new;
PLpgSQL_stmt_fors
*new;
new = malloc(sizeof(PLpgSQL_stmt_fors));
new = malloc(sizeof(PLpgSQL_stmt_fors));
memset(new, 0, sizeof(PLpgSQL_stmt_fors));
memset(new, 0, sizeof(PLpgSQL_stmt_fors));
new->cmd_type = PLPGSQL_STMT_FORS;
new->cmd_type = PLPGSQL_STMT_FORS;
new->lineno = $3;
new->lineno = $3;
new->label
= $1;
new->label
= $1;
switch ($4->dtype) {
switch ($4->dtype) {
case PLPGSQL_DTYPE_REC:
case PLPGSQL_DTYPE_REC:
new->rec = $4;
new->rec = $4;
break;
break;
case PLPGSQL_DTYPE_ROW:
case PLPGSQL_DTYPE_ROW:
new->row = (PLpgSQL_row *)$4;
new->row = (PLpgSQL_row *)$4;
break;
break;
default:
default:
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
}
}
new->query = $7;
new->query = $7;
new->body = $8;
new->body = $8;
plpgsql_ns_pop();
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body
stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body
{
{
PLpgSQL_stmt_dynfors *new;
PLpgSQL_stmt_dynfors *new;
new = malloc(sizeof(PLpgSQL_stmt_dynfors));
new = malloc(sizeof(PLpgSQL_stmt_dynfors));
memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
new->cmd_type = PLPGSQL_STMT_DYNFORS;
new->cmd_type = PLPGSQL_STMT_DYNFORS;
new->lineno = $3;
new->lineno = $3;
new->label
= $1;
new->label
= $1;
switch ($4->dtype) {
switch ($4->dtype) {
case PLPGSQL_DTYPE_REC:
case PLPGSQL_DTYPE_REC:
new->rec = $4;
new->rec = $4;
break;
break;
case PLPGSQL_DTYPE_ROW:
case PLPGSQL_DTYPE_ROW:
new->row = (PLpgSQL_row *)$4;
new->row = (PLpgSQL_row *)$4;
break;
break;
default:
default:
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "unknown dtype %d in stmt_dynfors", $4->dtype);
elog(ERROR, "unknown dtype %d in stmt_dynfors", $4->dtype);
}
}
new->query = $7;
new->query = $7;
new->body = $8;
new->body = $8;
plpgsql_ns_pop();
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
fors_target : T_RECORD
fors_target
: T_RECORD
{
{
$$ = yylval.rec;
$$ = yylval.rec;
}
}
| T_ROW
| T_ROW
{
{
$$ = (PLpgSQL_rec *)(yylval.row);
$$ = (PLpgSQL_rec *)(yylval.row);
}
}
;
;
stmt_select : K_SELECT lno
stmt_select
: K_SELECT lno
{
{
$$ = make_select_stmt();
$$ = make_select_stmt();
$$->lineno = $2;
$$->lineno = $2;
}
}
;
;
stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
stmt_exit
: K_EXIT lno opt_exitlabel opt_exitcond
{
{
PLpgSQL_stmt_exit *new;
PLpgSQL_stmt_exit *new;
new = malloc(sizeof(PLpgSQL_stmt_exit));
new = malloc(sizeof(PLpgSQL_stmt_exit));
memset(new, 0, sizeof(PLpgSQL_stmt_exit));
memset(new, 0, sizeof(PLpgSQL_stmt_exit));
new->cmd_type = PLPGSQL_STMT_EXIT;
new->cmd_type = PLPGSQL_STMT_EXIT;
new->lineno = $2;
new->lineno = $2;
new->label
= $3;
new->label
= $3;
new->cond
= $4;
new->cond
= $4;
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
stmt_return : K_RETURN lno
stmt_return
: K_RETURN lno
{
{
PLpgSQL_stmt_return *new;
PLpgSQL_stmt_return *new;
PLpgSQL_expr *expr = NULL;
PLpgSQL_expr *expr = NULL;
int
tok;
int
tok;
new = malloc(sizeof(PLpgSQL_stmt_return));
new = malloc(sizeof(PLpgSQL_stmt_return));
memset(new, 0, sizeof(PLpgSQL_stmt_return));
memset(new, 0, sizeof(PLpgSQL_stmt_return));
if (plpgsql_curr_compile->fn_retistuple) {
if (plpgsql_curr_compile->fn_retistuple) {
new->retistuple = true;
new->retistuple = true;
new->retrecno
= -1;
new->retrecno
= -1;
switch (tok = yylex()) {
switch (tok = yylex()) {
case K_NULL:
case K_NULL:
expr = NULL;
expr = NULL;
break;
break;
case T_ROW:
case T_ROW:
expr = make_tupret_expr(yylval.row);
expr = make_tupret_expr(yylval.row);
break;
break;
case T_RECORD:
case T_RECORD:
new->retrecno = yylval.rec->recno;
new->retrecno = yylval.rec->recno;
expr = NULL;
expr = NULL;
break;
break;
default:
default:
yyerror("return type mismatch in function returning table row");
yyerror("return type mismatch in function returning table row");
break;
break;
}
}
if (yylex() != ';') {
if (yylex() != ';') {
yyerror("expected ';'");
yyerror("expected ';'");
}
}
} else {
} else {
new->retistuple = false;
new->retistuple = false;
expr = plpgsql_read_expression(';', ";");
expr = plpgsql_read_expression(';', ";");
}
}
new->cmd_type = PLPGSQL_STMT_RETURN;
new->cmd_type = PLPGSQL_STMT_RETURN;
new->lineno = $2;
new->lineno = $2;
new->expr
= expr;
new->expr
= expr;
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
stmt_raise
: K_RAISE lno raise_level raise_msg raise_params ';'
{
{
PLpgSQL_stmt_raise
*new;
PLpgSQL_stmt_raise
*new;
new = malloc(sizeof(PLpgSQL_stmt_raise));
new = malloc(sizeof(PLpgSQL_stmt_raise));
new->cmd_type = PLPGSQL_STMT_RAISE;
new->cmd_type = PLPGSQL_STMT_RAISE;
new->lineno
= $2;
new->lineno
= $2;
new->elog_level
= $3;
new->elog_level
= $3;
new->message = $4;
new->message = $4;
new->nparams = $5.nused;
new->nparams = $5.nused;
new->params
= malloc(sizeof(int) * $5.nused);
new->params
= malloc(sizeof(int) * $5.nused);
memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused);
memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused);
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
| K_RAISE lno raise_level raise_msg ';'
| K_RAISE lno raise_level raise_msg ';'
{
{
PLpgSQL_stmt_raise
*new;
PLpgSQL_stmt_raise
*new;
new = malloc(sizeof(PLpgSQL_stmt_raise));
new = malloc(sizeof(PLpgSQL_stmt_raise));
new->cmd_type = PLPGSQL_STMT_RAISE;
new->cmd_type = PLPGSQL_STMT_RAISE;
new->lineno
= $2;
new->lineno
= $2;
new->elog_level
= $3;
new->elog_level
= $3;
new->message = $4;
new->message = $4;
new->nparams = 0;
new->nparams = 0;
new->params
= NULL;
new->params
= NULL;
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
raise_msg : T_STRING
raise_msg
: T_STRING
{
{
$$ = strdup(yytext);
$$ = strdup(yytext);
}
}
;
;
raise_level : K_EXCEPTION
raise_level
: K_EXCEPTION
{
{
$$ = ERROR;
$$ = ERROR;
}
}
| K_NOTICE
| K_NOTICE
{
{
$$ = NOTICE;
$$ = NOTICE;
}
}
| K_DEBUG
| K_DEBUG
{
{
$$ = DEBUG;
$$ = DEBUG;
}
}
;
;
raise_params : raise_params raise_param
raise_params : raise_params raise_param
{
{
if ($1.nused == $1.nalloc) {
if ($1.nused == $1.nalloc) {
$1.nalloc *= 2;
$1.nalloc *= 2;
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
}
}
$1.dtnums[$1.nused++] = $2;
$1.dtnums[$1.nused++] = $2;
$$.nalloc = $1.nalloc;
$$.nalloc = $1.nalloc;
$$.nused = $1.nused;
$$.nused = $1.nused;
$$.dtnums = $1.dtnums;
$$.dtnums = $1.dtnums;
}
}
| raise_param
| raise_param
{
{
$$.nalloc = 1;
$$.nalloc = 1;
$$.nused = 1;
$$.nused = 1;
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums[0] = $1;
$$.dtnums[0] = $1;
}
}
;
;
raise_param : ',' T_VARIABLE
raise_param
: ',' T_VARIABLE
{
{
$$ = yylval.var->varno;
$$ = yylval.var->varno;
}
}
| ',' T_RECFIELD
| ',' T_RECFIELD
{
{
$$ = yylval.recfield->rfno;
$$ = yylval.recfield->rfno;
}
}
| ',' T_TGARGV
| ',' T_TGARGV
{
{
$$ = yylval.trigarg->dno;
$$ = yylval.trigarg->dno;
}
}
;
;
loop_body : proc_sect K_END K_LOOP ';'
loop_body
: proc_sect K_END K_LOOP ';'
{ $$ = $1; }
{ $$ = $1; }
;
;
stmt_execsql : execsql_start lno
stmt_execsql : execsql_start lno
{
{
PLpgSQL_stmt_execsql *new;
PLpgSQL_stmt_execsql *new;
new = malloc(sizeof(PLpgSQL_stmt_execsql));
new = malloc(sizeof(PLpgSQL_stmt_execsql));
new->cmd_type = PLPGSQL_STMT_EXECSQL;
new->cmd_type = PLPGSQL_STMT_EXECSQL;
new->lineno = $2;
new->lineno = $2;
new->sqlstmt = read_sqlstmt(';', ";", $1);
new->sqlstmt = read_sqlstmt(';', ";", $1);
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
stmt_dynexecute
: K_EXECUTE lno expr_until_semi
stmt_dynexecute
: K_EXECUTE lno expr_until_semi
{
{
PLpgSQL_stmt_dynexecute
*new;
PLpgSQL_stmt_dynexecute
*new;
new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
new->lineno = $2;
new->lineno = $2;
new->query
= $3;
new->query
= $3;
$$ = (PLpgSQL_stmt *)new;
$$ = (PLpgSQL_stmt *)new;
}
}
;
;
execsql_start : T_WORD
execsql_start : T_WORD
{ $$ = strdup(yytext); }
{ $$ = strdup(yytext); }
| T_ERROR
| T_ERROR
{ $$ = strdup(yytext); }
{ $$ = strdup(yytext); }
;
;
expr_until_semi
:
expr_until_semi
:
{ $$ = plpgsql_read_expression(';', ";"); }
{ $$ = plpgsql_read_expression(';', ";"); }
;
;
expr_until_then
:
expr_until_then
:
{ $$ = plpgsql_read_expression(K_THEN, "THEN"); }
{ $$ = plpgsql_read_expression(K_THEN, "THEN"); }
;
;
expr_until_loop
:
expr_until_loop
:
{ $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
{ $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
;
;
opt_label :
opt_label
:
{
{
plpgsql_ns_push(NULL);
plpgsql_ns_push(NULL);
$$ = NULL;
$$ = NULL;
}
}
| '<' '<' opt_lblname '>' '>'
| '<' '<' opt_lblname '>' '>'
{
{
plpgsql_ns_push($3);
plpgsql_ns_push($3);
$$ = $3;
$$ = $3;
}
}
;
;
opt_exitlabel :
opt_exitlabel :
{ $$ = NULL; }
{ $$ = NULL; }
| T_LABEL
| T_LABEL
{ $$ = strdup(yytext); }
{ $$ = strdup(yytext); }
;
;
opt_exitcond : ';'
opt_exitcond : ';'
{ $$ = NULL; }
{ $$ = NULL; }
| K_WHEN expr_until_semi
| K_WHEN expr_until_semi
{ $$ = $2; }
{ $$ = $2; }
;
;
opt_lblname : T_WORD
opt_lblname
: T_WORD
{ $$ = strdup(yytext); }
{ $$ = strdup(yytext); }
;
;
lno :
lno
:
{
{
plpgsql_error_lineno = yylineno;
plpgsql_error_lineno = yylineno;
$$ = yylineno;
$$ = yylineno;
}
}
;
;
%%
%%
...
@@ -1244,237 +1244,104 @@ lno :
...
@@ -1244,237 +1244,104 @@ lno :
PLpgSQL_expr *
PLpgSQL_expr *
plpgsql_read_expression (int until, char *s)
plpgsql_read_expression (int until, char *s)
{
{
return read_sqlstmt(until, s, "SELECT ");
return read_sqlstmt(until, s, "SELECT ");
}
}
static PLpgSQL_expr *
static PLpgSQL_expr *
read_sqlstmt (int until, char *s, char *sqlstart)
read_sqlstmt (int until, char *s, char *sqlstart)
{
{
int tok;
int tok;
int lno;
int lno;
PLpgSQL_dstring ds;
PLpgSQL_dstring ds;
int nparams = 0;
int nparams = 0;
int params[1024];
int params[1024];
char buf[32];
char buf[32];
PLpgSQL_expr *expr;
PLpgSQL_expr *expr;
lno = yylineno;
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, sqlstart);
while((tok = yylex()) != until) {
if (tok == ';') break;
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
switch (tok) {
case T_VARIABLE:
params[nparams] = yylval.var->varno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
case T_RECFIELD:
params[nparams] = yylval.recfield->rfno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
case T_TGARGV:
params[nparams] = yylval.trigarg->dno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
default:
if (tok == 0) {
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
elog(ERROR, "missing %s at end of SQL statement", s);
}
plpgsql_dstring_append(&ds, yytext);
break;
}
}
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->plan = NULL;
expr->nparams = nparams;
while(nparams-- > 0) {
expr->params[nparams] = params[nparams];
}
plpgsql_dstring_free(&ds);
return expr;
}
static PLpgSQL_stmt *
make_select_stmt()
{
int tok;
int lno;
PLpgSQL_dstring ds;
int nparams = 0;
int params[1024];
char buf[32];
PLpgSQL_expr *expr;
PLpgSQL_row *row = NULL;
PLpgSQL_rec *rec = NULL;
PLpgSQL_stmt_select *select;
int have_nexttok = 0;
lno = yylineno;
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
while((tok = yylex()) != K_INTO) {
if (tok == ';') {
PLpgSQL_stmt_execsql *execsql;
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->plan = NULL;
expr->nparams = nparams;
while(nparams-- > 0) {
expr->params[nparams] = params[nparams];
}
plpgsql_dstring_free(&ds);
execsql = malloc(sizeof(PLpgSQL_stmt_execsql))
;
lno = yylineno
;
execsql->cmd_type = PLPGSQL_STMT_EXECSQL
;
plpgsql_dstring_init(&ds)
;
execsql->sqlstmt = expr
;
plpgsql_dstring_append(&ds, sqlstart)
;
return (PLpgSQL_stmt *)execsql;
while((tok = yylex()) != until) {
}
if (tok == ';') break;
if (plpgsql_SpaceScanned) {
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
plpgsql_dstring_append(&ds, " ");
}
switch (tok) {
case T_VARIABLE:
params[nparams] = yylval.var->varno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
case T_RECFIELD:
params[nparams] = yylval.recfield->rfno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
case T_TGARGV:
params[nparams] = yylval.trigarg->dno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
default:
if (tok == 0) {
plpgsql_error_lineno = yylineno;
plpgsql_comperrinfo();
elog(ERROR, "unexpected end of file");
}
}
plpgsql_dstring_append(&ds, yytext);
break;
}
}
tok = yylex();
switch (tok) {
case T_ROW:
row = yylval.row;
break;
case T_RECORD:
rec = yylval.rec;
break;
case T_VARIABLE:
case T_RECFIELD:
{
PLpgSQL_var *var;
PLpgSQL_recfield *recfield;
int nfields = 1;
char *fieldnames[1024];
int varnos[1024];
switch (tok) {
switch (tok) {
case T_VARIABLE:
var = yylval.var;
fieldnames[0] = strdup(yytext);
varnos[0] = var->varno;
break;
case T_RECFIELD:
recfield = yylval.recfield;
fieldnames[0] = strdup(yytext);
varnos[0] = recfield->rfno;
break;
}
while ((tok = yylex()) == ',') {
tok = yylex();
switch(tok) {
case T_VARIABLE:
case T_VARIABLE:
var = yylval.var
;
params[nparams] = yylval.var->varno
;
fieldnames[nfields] = strdup(yytext
);
sprintf(buf, " $%d ", ++nparams
);
varnos[nfields++] = var->varno
;
plpgsql_dstring_append(&ds, buf)
;
break;
break;
case T_RECFIELD:
case T_RECFIELD:
recfield = yylval.recfield;
params[nparams] = yylval.recfield->rfno;
fieldnames[0] = strdup(yytext);
sprintf(buf, " $%d ", ++nparams);
varnos[0] = recfield->rfno;
plpgsql_dstring_append(&ds, buf);
break;
break;
case T_TGARGV:
params[nparams] = yylval.trigarg->dno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
default:
default:
elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
if (tok == 0) {
}
plpgsql_error_lineno = lno;
}
plpgsql_comperrinfo();
row = malloc(sizeof(PLpgSQL_row));
elog(ERROR, "missing %s at end of SQL statement", s);
row->dtype = PLPGSQL_DTYPE_ROW;
}
row->refname = strdup("*internal*");
plpgsql_dstring_append(&ds, yytext);
row->lineno = yylineno;
break;
row->rowtypeclass = InvalidOid;
row->nfields = nfields;
row->fieldnames = malloc(sizeof(char *) * nfields);
row->varnos = malloc(sizeof(int) * nfields);
while (--nfields >= 0) {
row->fieldnames[nfields] = fieldnames[nfields];
row->varnos[nfields] = varnos[nfields];
}
}
}
plpgsql_adddatum((PLpgSQL_datum *)row);
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->plan = NULL;
expr->nparams = nparams;
while(nparams-- > 0) {
expr->params[nparams] = params[nparams];
}
plpgsql_dstring_free(&ds);
have_nexttok = 1;
return expr;
}
}
break;
default:
{
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
plpgsql_dstring_append(&ds, yytext);
while(1) {
static PLpgSQL_stmt *
tok = yylex();
make_select_stmt()
if (tok == ';') {
{
PLpgSQL_stmt_execsql *execsql;
int tok;
int lno;
PLpgSQL_dstring ds;
int nparams = 0;
int params[1024];
char buf[32];
PLpgSQL_expr *expr;
PLpgSQL_row *row = NULL;
PLpgSQL_rec *rec = NULL;
PLpgSQL_stmt_select *select;
int have_nexttok = 0;
lno = yylineno;
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
while((tok = yylex()) != K_INTO) {
if (tok == ';') {
PLpgSQL_stmt_execsql *execsql;
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->dtype
= PLPGSQL_DTYPE_EXPR;
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->query
= strdup(plpgsql_dstring_get(&ds));
expr->plan = NULL;
expr->plan
= NULL;
expr->nparams = nparams;
expr->nparams
= nparams;
while(nparams-- > 0) {
while(nparams-- > 0) {
expr->params[nparams] = params[nparams];
expr->params[nparams] = params[nparams];
}
}
plpgsql_dstring_free(&ds);
plpgsql_dstring_free(&ds);
...
@@ -1483,134 +1350,267 @@ make_select_stmt()
...
@@ -1483,134 +1350,267 @@ make_select_stmt()
execsql->sqlstmt = expr;
execsql->sqlstmt = expr;
return (PLpgSQL_stmt *)execsql;
return (PLpgSQL_stmt *)execsql;
}
}
if (plpgsql_SpaceScanned) {
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
plpgsql_dstring_append(&ds, " ");
}
}
switch (tok) {
switch (tok) {
case T_VARIABLE:
case T_VARIABLE:
params[nparams] = yylval.var->varno;
params[nparams] = yylval.var->varno;
sprintf(buf, " $%d ", ++nparams);
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
plpgsql_dstring_append(&ds, buf);
break;
break;
case T_RECFIELD:
case T_RECFIELD:
params[nparams] = yylval.recfield->rfno;
params[nparams] = yylval.recfield->rfno;
sprintf(buf, " $%d ", ++nparams);
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
plpgsql_dstring_append(&ds, buf);
break;
break;
case T_TGARGV:
case T_TGARGV:
params[nparams] = yylval.trigarg->dno;
params[nparams] = yylval.trigarg->dno;
sprintf(buf, " $%d ", ++nparams);
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
plpgsql_dstring_append(&ds, buf);
break;
break;
default:
default:
if (tok == 0) {
if (tok == 0) {
plpgsql_error_lineno = yylineno;
plpgsql_error_lineno = yylineno;
plpgsql_comperrinfo();
plpgsql_comperrinfo();
elog(ERROR, "unexpected end of file");
elog(ERROR, "unexpected end of file");
}
}
plpgsql_dstring_append(&ds, yytext);
plpgsql_dstring_append(&ds, yytext);
break;
break;
}
}
}
}
}
/************************************************************
* Eat up the rest of the statement after the target fields
************************************************************/
while(1) {
if (!have_nexttok) {
tok = yylex();
}
have_nexttok = 0;
if (tok == ';') {
break;
}
}
if (plpgsql_SpaceScanned) {
tok = yylex();
plpgsql_dstring_append(&ds, " ");
}
switch (tok) {
switch (tok) {
case T_VARIABLE:
case T_ROW:
params[nparams] = yylval.var->varno;
row = yylval.row;
sprintf(buf, " $%d ", ++nparams);
break;
plpgsql_dstring_append(&ds, buf);
break;
case T_RECORD:
rec = yylval.rec;
case T_RECFIELD:
break;
params[nparams] = yylval.recfield->rfno;
sprintf(buf, " $%d ", ++nparams);
case T_VARIABLE:
plpgsql_dstring_append(&ds, buf);
case T_RECFIELD:
break;
{
PLpgSQL_var *var;
case T_TGARGV:
PLpgSQL_recfield *recfield;
params[nparams] = yylval.trigarg->dno;
int nfields = 1;
sprintf(buf, " $%d ", ++nparams);
char *fieldnames[1024];
plpgsql_dstring_append(&ds, buf);
int varnos[1024];
break;
switch (tok) {
default:
case T_VARIABLE:
if (tok == 0) {
var = yylval.var;
plpgsql_error_lineno = yylineno;
fieldnames[0] = strdup(yytext);
plpgsql_comperrinfo();
varnos[0] = var->varno;
elog(ERROR, "unexpected end of file");
break;
case T_RECFIELD:
recfield = yylval.recfield;
fieldnames[0] = strdup(yytext);
varnos[0] = recfield->rfno;
break;
}
while ((tok = yylex()) == ',') {
tok = yylex();
switch(tok) {
case T_VARIABLE:
var = yylval.var;
fieldnames[nfields] = strdup(yytext);
varnos[nfields++] = var->varno;
break;
case T_RECFIELD:
recfield = yylval.recfield;
fieldnames[0] = strdup(yytext);
varnos[0] = recfield->rfno;
break;
default:
elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
}
}
row = malloc(sizeof(PLpgSQL_row));
row->dtype = PLPGSQL_DTYPE_ROW;
row->refname = strdup("*internal*");
row->lineno = yylineno;
row->rowtypeclass = InvalidOid;
row->nfields = nfields;
row->fieldnames = malloc(sizeof(char *) * nfields);
row->varnos = malloc(sizeof(int) * nfields);
while (--nfields >= 0) {
row->fieldnames[nfields] = fieldnames[nfields];
row->varnos[nfields] = varnos[nfields];
}
plpgsql_adddatum((PLpgSQL_datum *)row);
have_nexttok = 1;
}
break;
default:
{
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
plpgsql_dstring_append(&ds, yytext);
while(1) {
tok = yylex();
if (tok == ';') {
PLpgSQL_stmt_execsql *execsql;
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->plan = NULL;
expr->nparams = nparams;
while(nparams-- > 0) {
expr->params[nparams] = params[nparams];
}
plpgsql_dstring_free(&ds);
execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
execsql->sqlstmt = expr;
return (PLpgSQL_stmt *)execsql;
}
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
switch (tok) {
case T_VARIABLE:
params[nparams] = yylval.var->varno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
case T_RECFIELD:
params[nparams] = yylval.recfield->rfno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
case T_TGARGV:
params[nparams] = yylval.trigarg->dno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
default:
if (tok == 0) {
plpgsql_error_lineno = yylineno;
plpgsql_comperrinfo();
elog(ERROR, "unexpected end of file");
}
plpgsql_dstring_append(&ds, yytext);
break;
}
}
}
}
/************************************************************
* Eat up the rest of the statement after the target fields
************************************************************/
while(1) {
if (!have_nexttok) {
tok = yylex();
}
have_nexttok = 0;
if (tok == ';') {
break;
}
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
switch (tok) {
case T_VARIABLE:
params[nparams] = yylval.var->varno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
case T_RECFIELD:
params[nparams] = yylval.recfield->rfno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
case T_TGARGV:
params[nparams] = yylval.trigarg->dno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
default:
if (tok == 0) {
plpgsql_error_lineno = yylineno;
plpgsql_comperrinfo();
elog(ERROR, "unexpected end of file");
}
plpgsql_dstring_append(&ds, yytext);
break;
}
}
plpgsql_dstring_append(&ds, yytext);
break;
}
}
}
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (nparams - 1));
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (nparams - 1));
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->plan = NULL;
expr->plan = NULL;
expr->nparams = nparams;
expr->nparams = nparams;
while(nparams-- > 0) {
while(nparams-- > 0) {
expr->params[nparams] = params[nparams];
expr->params[nparams] = params[nparams];
}
}
plpgsql_dstring_free(&ds);
plpgsql_dstring_free(&ds);
select = malloc(sizeof(PLpgSQL_stmt_select));
select = malloc(sizeof(PLpgSQL_stmt_select));
memset(select, 0, sizeof(PLpgSQL_stmt_select));
memset(select, 0, sizeof(PLpgSQL_stmt_select));
select->cmd_type = PLPGSQL_STMT_SELECT;
select->cmd_type = PLPGSQL_STMT_SELECT;
select->rec = rec;
select->rec = rec;
select->row = row;
select->row = row;
select->query = expr;
select->query = expr;
return (PLpgSQL_stmt *)select;
return (PLpgSQL_stmt *)select;
}
}
static PLpgSQL_expr *
static PLpgSQL_expr *
make_tupret_expr(PLpgSQL_row *row)
make_tupret_expr(PLpgSQL_row *row)
{
{
PLpgSQL_dstring
ds;
PLpgSQL_dstring
ds;
PLpgSQL_expr
*expr;
PLpgSQL_expr
*expr;
int
i;
int
i;
char
buf[16];
char
buf[16];
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
expr->dtype
= PLPGSQL_DTYPE_EXPR;
expr->dtype
= PLPGSQL_DTYPE_EXPR;
plpgsql_dstring_init(&ds);
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
plpgsql_dstring_append(&ds, "SELECT ");
for (i = 0; i < row->nfields; i++) {
for (i = 0; i < row->nfields; i++) {
sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
plpgsql_dstring_append(&ds, buf);
plpgsql_dstring_append(&ds, buf);
expr->params[i] = row->varnos[i];
expr->params[i] = row->varnos[i];
}
}
expr->query
= strdup(plpgsql_dstring_get(&ds));
expr->query
= strdup(plpgsql_dstring_get(&ds));
expr->plan
= NULL;
expr->plan
= NULL;
expr->plan_argtypes = NULL;
expr->plan_argtypes = NULL;
expr->nparams
= row->nfields;
expr->nparams
= row->nfields;
plpgsql_dstring_free(&ds);
plpgsql_dstring_free(&ds);
return expr;
return expr;
}
}
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment