Commit b54073ea authored by Bruce Momjian's avatar Bruce Momjian

Convert to standard 4-space tabs.

parent 26608036
%{
/**********************************************************************
* gram.y - Parser for the PL/pgSQL
* procedural language
* gram.y - Parser for the PL/pgSQL
* procedural language
*
* 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,
* distribute, and license this software and its documentation
* for any purpose, provided that existing copyright notices are
* retained in all copies and that this notice is included
* verbatim in any distributions. No written agreement, license,
* or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their
* author and need not follow the licensing terms described
* here, provided that the new terms are clearly indicated on
* the first page of each file where they apply.
* The author hereby grants permission to use, copy, modify,
* distribute, and license this software and its documentation
* for any purpose, provided that existing copyright notices are
* retained in all copies and that this notice is included
* verbatim in any distributions. No written agreement, license,
* or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their
* author and need not follow the licensing terms described
* here, provided that the new terms are clearly indicated on
* the first page of each file where they apply.
*
* IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
* SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
* IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
* SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
* IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
* AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS.
* THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
* AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS.
*
**********************************************************************/
......@@ -52,61 +52,61 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%}
%union {
int32 ival;
char *str;
struct {
char *name;
int lineno;
} varname;
struct {
int nalloc;
int nused;
int *dtnums;
} dtlist;
struct {
int reverse;
PLpgSQL_expr *expr;
} forilow;
struct {
char *label;
int n_initvars;
int *initvarnos;
} declhdr;
PLpgSQL_type *dtype;
PLpgSQL_var *var;
PLpgSQL_row *row;
PLpgSQL_rec *rec;
PLpgSQL_recfield *recfield;
PLpgSQL_trigarg *trigarg;
PLpgSQL_expr *expr;
PLpgSQL_stmt *stmt;
PLpgSQL_stmts *stmts;
PLpgSQL_stmt_block *program;
PLpgSQL_nsitem *nsitem;
int32 ival;
char *str;
struct {
char *name;
int lineno;
} varname;
struct {
int nalloc;
int nused;
int *dtnums;
} dtlist;
struct {
int reverse;
PLpgSQL_expr *expr;
} forilow;
struct {
char *label;
int n_initvars;
int *initvarnos;
} declhdr;
PLpgSQL_type *dtype;
PLpgSQL_var *var;
PLpgSQL_row *row;
PLpgSQL_rec *rec;
PLpgSQL_recfield *recfield;
PLpgSQL_trigarg *trigarg;
PLpgSQL_expr *expr;
PLpgSQL_stmt *stmt;
PLpgSQL_stmts *stmts;
PLpgSQL_stmt_block *program;
PLpgSQL_nsitem *nsitem;
}
%type <declhdr> decl_sect
%type <varname> decl_varname
%type <str> decl_renname
%type <declhdr> decl_sect
%type <varname> decl_varname
%type <str> decl_renname
%type <ival> decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval
%type <expr> decl_defval
%type <dtype> decl_datatype, decl_dtypename
%type <row> decl_rowtype
%type <row> decl_rowtype
%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> opt_exitcond
%type <ival> assign_var
%type <var> fori_var
%type <varname> fori_varname
%type <forilow> fori_lower
%type <rec> fors_target
%type <var> fori_var
%type <varname> fori_varname
%type <forilow> fori_lower
%type <rec> fors_target
%type <str> opt_lblname, opt_label
%type <str> opt_exitlabel
%type <str> execsql_start
%type <str> opt_lblname, opt_label
%type <str> opt_exitlabel
%type <str> execsql_start
%type <stmts> proc_sect, proc_stmts, stmt_else, loop_body
%type <stmt> proc_stmt, pl_block
......@@ -117,16 +117,16 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%type <dtlist> raise_params
%type <ival> raise_level, raise_param
%type <str> raise_msg
%type <str> raise_msg
%type <dtlist> getdiag_items, getdiag_targets
%type <ival> getdiag_item, getdiag_target
%type <ival> lno
/*
* Keyword tokens
*/
/*
* Keyword tokens
*/
%token K_ALIAS
%token K_ASSIGN
%token K_BEGIN
......@@ -152,7 +152,7 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%token K_NOTICE
%token K_NULL
%token K_PERFORM
%token K_PROCESSED
%token K_PROCESSED
%token K_RAISE
%token K_RECORD
%token K_RENAME
......@@ -166,9 +166,9 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%token K_WHEN
%token K_WHILE
/*
* Other tokens
*/
/*
* Other tokens
*/
%token T_FUNCTION
%token T_TRIGGER
%token T_CHAR
......@@ -192,1047 +192,1047 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
%%
pl_function : T_FUNCTION comp_optsect pl_block
{
yylval.program = (PLpgSQL_stmt_block *)$3;
}
| T_TRIGGER comp_optsect pl_block
{
yylval.program = (PLpgSQL_stmt_block *)$3;
}
;
pl_function : T_FUNCTION comp_optsect pl_block
{
yylval.program = (PLpgSQL_stmt_block *)$3;
}
| T_TRIGGER comp_optsect pl_block
{
yylval.program = (PLpgSQL_stmt_block *)$3;
}
;
comp_optsect :
| comp_options
;
| comp_options
;
comp_options : comp_options comp_option
| comp_option
;
comp_option : O_OPTION O_DUMP
{
plpgsql_DumpExecTree = 1;
}
;
pl_block : decl_sect K_BEGIN lno proc_sect K_END ';'
{
PLpgSQL_stmt_block *new;
new = malloc(sizeof(PLpgSQL_stmt_block));
memset(new, 0, sizeof(PLpgSQL_stmt_block));
new->cmd_type = PLPGSQL_STMT_BLOCK;
new->lineno = $3;
new->label = $1.label;
new->n_initvars = $1.n_initvars;
new->initvarnos = $1.initvarnos;
new->body = $4;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
;
decl_sect : opt_label
{
plpgsql_ns_setlocal(false);
$$.label = $1;
$$.n_initvars = 0;
$$.initvarnos = NULL;
plpgsql_add_initdatums(NULL);
}
| opt_label decl_start
{
plpgsql_ns_setlocal(false);
$$.label = $1;
$$.n_initvars = 0;
$$.initvarnos = NULL;
plpgsql_add_initdatums(NULL);
}
| opt_label decl_start decl_stmts
{
plpgsql_ns_setlocal(false);
if ($3 != NULL) {
$$.label = $3;
} else {
$$.label = $1;
}
$$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
}
;
decl_start : K_DECLARE
{
plpgsql_ns_setlocal(true);
}
;
decl_stmts : decl_stmts decl_stmt
{
$$ = $2;
}
| decl_stmt
{
$$ = $1;
}
;
decl_stmt : '<' '<' opt_lblname '>' '>'
{
$$ = $3;
}
| K_DECLARE
{
$$ = NULL;
}
| decl_statement
{
$$ = NULL;
}
;
| comp_option
;
comp_option : O_OPTION O_DUMP
{
plpgsql_DumpExecTree = 1;
}
;
pl_block : decl_sect K_BEGIN lno proc_sect K_END ';'
{
PLpgSQL_stmt_block *new;
new = malloc(sizeof(PLpgSQL_stmt_block));
memset(new, 0, sizeof(PLpgSQL_stmt_block));
new->cmd_type = PLPGSQL_STMT_BLOCK;
new->lineno = $3;
new->label = $1.label;
new->n_initvars = $1.n_initvars;
new->initvarnos = $1.initvarnos;
new->body = $4;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
;
decl_sect : opt_label
{
plpgsql_ns_setlocal(false);
$$.label = $1;
$$.n_initvars = 0;
$$.initvarnos = NULL;
plpgsql_add_initdatums(NULL);
}
| opt_label decl_start
{
plpgsql_ns_setlocal(false);
$$.label = $1;
$$.n_initvars = 0;
$$.initvarnos = NULL;
plpgsql_add_initdatums(NULL);
}
| opt_label decl_start decl_stmts
{
plpgsql_ns_setlocal(false);
if ($3 != NULL) {
$$.label = $3;
} else {
$$.label = $1;
}
$$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
}
;
decl_start : K_DECLARE
{
plpgsql_ns_setlocal(true);
}
;
decl_stmts : decl_stmts decl_stmt
{
$$ = $2;
}
| decl_stmt
{
$$ = $1;
}
;
decl_stmt : '<' '<' opt_lblname '>' '>'
{
$$ = $3;
}
| K_DECLARE
{
$$ = NULL;
}
| decl_statement
{
$$ = NULL;
}
;
decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
{
PLpgSQL_var *new;
new = malloc(sizeof(PLpgSQL_var));
new->dtype = PLPGSQL_DTYPE_VAR;
new->refname = $1.name;
new->lineno = $1.lineno;
new->datatype = $3;
new->isconst = $2;
new->notnull = $4;
new->default_val = $5;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
$1.name);
}
| decl_varname K_RECORD ';'
{
PLpgSQL_rec *new;
new = malloc(sizeof(PLpgSQL_var));
new->dtype = PLPGSQL_DTYPE_REC;
new->refname = $1.name;
new->lineno = $1.lineno;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
$1.name);
}
| decl_varname decl_rowtype ';'
{
$2->dtype = PLPGSQL_DTYPE_ROW;
$2->refname = $1.name;
$2->lineno = $1.lineno;
plpgsql_adddatum((PLpgSQL_datum *)$2);
plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
$1.name);
}
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
{
plpgsql_ns_additem($4->itemtype,
$4->itemno, $1.name);
}
| K_RENAME decl_renname K_TO decl_renname ';'
{
plpgsql_ns_rename($2, $4);
}
;
{
PLpgSQL_var *new;
new = malloc(sizeof(PLpgSQL_var));
new->dtype = PLPGSQL_DTYPE_VAR;
new->refname = $1.name;
new->lineno = $1.lineno;
new->datatype = $3;
new->isconst = $2;
new->notnull = $4;
new->default_val = $5;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
$1.name);
}
| decl_varname K_RECORD ';'
{
PLpgSQL_rec *new;
new = malloc(sizeof(PLpgSQL_var));
new->dtype = PLPGSQL_DTYPE_REC;
new->refname = $1.name;
new->lineno = $1.lineno;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
$1.name);
}
| decl_varname decl_rowtype ';'
{
$2->dtype = PLPGSQL_DTYPE_ROW;
$2->refname = $1.name;
$2->lineno = $1.lineno;
plpgsql_adddatum((PLpgSQL_datum *)$2);
plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
$1.name);
}
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
{
plpgsql_ns_additem($4->itemtype,
$4->itemno, $1.name);
}
| K_RENAME decl_renname K_TO decl_renname ';'
{
plpgsql_ns_rename($2, $4);
}
;
decl_aliasitem : T_WORD
{
PLpgSQL_nsitem *nsi;
char *name;
plpgsql_ns_setlocal(false);
name = plpgsql_tolower(yytext);
if (name[0] != '$') {
elog(ERROR, "can only alias positional parameters");
}
nsi = plpgsql_ns_lookup(name, NULL);
if (nsi == NULL) {
elog(ERROR, "function has no parameter %s", name);
}
plpgsql_ns_setlocal(true);
$$ = nsi;
}
;
{
PLpgSQL_nsitem *nsi;
char *name;
plpgsql_ns_setlocal(false);
name = plpgsql_tolower(yytext);
if (name[0] != '$') {
elog(ERROR, "can only alias positional parameters");
}
nsi = plpgsql_ns_lookup(name, NULL);
if (nsi == NULL) {
elog(ERROR, "function has no parameter %s", name);
}
plpgsql_ns_setlocal(true);
$$ = nsi;
}
;
decl_rowtype : T_ROW
{
$$ = yylval.row;
}
;
{
$$ = yylval.row;
}
;
decl_varname : T_WORD
{
/* name should be malloc'd for use as varname */
$$.name = strdup(plpgsql_tolower(yytext));
$$.lineno = yylineno;
}
;
{
/* name should be malloc'd for use as varname */
$$.name = strdup(plpgsql_tolower(yytext));
$$.lineno = yylineno;
}
;
decl_renname : T_WORD
{
/* the result must be palloc'd, see plpgsql_ns_rename */
$$ = plpgsql_tolower(yytext);
}
;
decl_const :
{ $$ = 0; }
| K_CONSTANT
{ $$ = 1; }
;
{
/* the result must be palloc'd, see plpgsql_ns_rename */
$$ = plpgsql_tolower(yytext);
}
;
decl_const :
{ $$ = 0; }
| K_CONSTANT
{ $$ = 1; }
;
decl_datatype : decl_dtypename
{
$$ = $1;
}
;
{
$$ = $1;
}
;
decl_dtypename : T_DTYPE
{
$$ = yylval.dtype;
}
| T_CHAR decl_atttypmod
{
if ($2 < 0) {
plpgsql_parse_word("char");
$$ = yylval.dtype;
} else {
plpgsql_parse_word("bpchar");
$$ = yylval.dtype;
$$->atttypmod = $2;
}
}
| T_VARCHAR decl_atttypmod
{
plpgsql_parse_word("varchar");
$$ = yylval.dtype;
$$->atttypmod = $2;
}
| T_BPCHAR '(' decl_atttypmodval ')'
{
plpgsql_parse_word("bpchar");
$$ = yylval.dtype;
$$->atttypmod = $3;
}
;
{
$$ = yylval.dtype;
}
| T_CHAR decl_atttypmod
{
if ($2 < 0) {
plpgsql_parse_word("char");
$$ = yylval.dtype;
} else {
plpgsql_parse_word("bpchar");
$$ = yylval.dtype;
$$->atttypmod = $2;
}
}
| T_VARCHAR decl_atttypmod
{
plpgsql_parse_word("varchar");
$$ = yylval.dtype;
$$->atttypmod = $2;
}
| T_BPCHAR '(' decl_atttypmodval ')'
{
plpgsql_parse_word("bpchar");
$$ = yylval.dtype;
$$->atttypmod = $3;
}
;
decl_atttypmod :
{
$$ = -1;
}
| '(' decl_atttypmodval ')'
{
$$ = $2;
}
;
decl_atttypmodval : T_NUMBER
{
$$ = pg_atoi(yytext, sizeof(int16), '\0') + VARHDRSZ;
}
;
{
$$ = -1;
}
| '(' decl_atttypmodval ')'
{
$$ = $2;
}
;
decl_atttypmodval : T_NUMBER
{
$$ = pg_atoi(yytext, sizeof(int16), '\0') + VARHDRSZ;
}
;
decl_notnull :
{ $$ = 0; }
| K_NOT K_NULL
{ $$ = 1; }
;
decl_defval : ';'
{ $$ = NULL; }
| decl_defkey
{
int tok;
int lno;
PLpgSQL_dstring ds;
PLpgSQL_expr *expr;
lno = yylineno;
expr = malloc(sizeof(PLpgSQL_expr));
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->plan = NULL;
expr->nparams = 0;
tok = yylex();
switch (tok) {
case 0:
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
elog(ERROR, "unexpected end of file");
case K_NULL:
if (yylex() != ';') {
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
elog(ERROR, "expectec ; after NULL");
}
free(expr);
plpgsql_dstring_free(&ds);
$$ = NULL;
break;
default:
plpgsql_dstring_append(&ds, yytext);
while ((tok = yylex()) != ';') {
if (tok == 0) {
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
elog(ERROR, "unterminated default value");
}
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
plpgsql_dstring_append(&ds, yytext);
}
expr->query = strdup(plpgsql_dstring_get(&ds));
plpgsql_dstring_free(&ds);
$$ = expr;
break;
}
}
;
decl_defkey : K_ASSIGN
| K_DEFAULT
proc_sect :
{
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
$$ = new;
}
| proc_stmts
{
$$ = $1;
}
;
proc_stmts : proc_stmts proc_stmt
{
if ($1->stmts_used == $1->stmts_alloc) {
$1->stmts_alloc *= 2;
$1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
}
$1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
$$ = $1;
}
| proc_stmt
{
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
new->stmts_alloc = 64;
new->stmts_used = 1;
new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
new->stmts[0] = (struct PLpgSQL_stmt *)$1;
$$ = new;
}
;
proc_stmt : pl_block
{ $$ = $1; }
| stmt_assign
{ $$ = $1; }
| stmt_if
{ $$ = $1; }
| stmt_loop
{ $$ = $1; }
| stmt_while
{ $$ = $1; }
| stmt_fori
{ $$ = $1; }
| stmt_fors
{ $$ = $1; }
| stmt_select
{ $$ = $1; }
| stmt_exit
{ $$ = $1; }
| stmt_return
{ $$ = $1; }
| stmt_raise
{ $$ = $1; }
| stmt_execsql
{ $$ = $1; }
| stmt_dynexecute
{ $$ = $1; }
| stmt_dynfors
{ $$ = $1; }
| stmt_perform
{ $$ = $1; }
| stmt_getdiag
{ $$ = $1; }
;
{ $$ = 0; }
| K_NOT K_NULL
{ $$ = 1; }
;
decl_defval : ';'
{ $$ = NULL; }
| decl_defkey
{
int tok;
int lno;
PLpgSQL_dstring ds;
PLpgSQL_expr *expr;
lno = yylineno;
expr = malloc(sizeof(PLpgSQL_expr));
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
expr->dtype = PLPGSQL_DTYPE_EXPR;
expr->plan = NULL;
expr->nparams = 0;
tok = yylex();
switch (tok) {
case 0:
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
elog(ERROR, "unexpected end of file");
case K_NULL:
if (yylex() != ';') {
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
elog(ERROR, "expectec ; after NULL");
}
free(expr);
plpgsql_dstring_free(&ds);
$$ = NULL;
break;
default:
plpgsql_dstring_append(&ds, yytext);
while ((tok = yylex()) != ';') {
if (tok == 0) {
plpgsql_error_lineno = lno;
plpgsql_comperrinfo();
elog(ERROR, "unterminated default value");
}
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
plpgsql_dstring_append(&ds, yytext);
}
expr->query = strdup(plpgsql_dstring_get(&ds));
plpgsql_dstring_free(&ds);
$$ = expr;
break;
}
}
;
decl_defkey : K_ASSIGN
| K_DEFAULT
proc_sect :
{
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
$$ = new;
}
| proc_stmts
{
$$ = $1;
}
;
proc_stmts : proc_stmts proc_stmt
{
if ($1->stmts_used == $1->stmts_alloc) {
$1->stmts_alloc *= 2;
$1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
}
$1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
$$ = $1;
}
| proc_stmt
{
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
new->stmts_alloc = 64;
new->stmts_used = 1;
new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
new->stmts[0] = (struct PLpgSQL_stmt *)$1;
$$ = new;
}
;
proc_stmt : pl_block
{ $$ = $1; }
| stmt_assign
{ $$ = $1; }
| stmt_if
{ $$ = $1; }
| stmt_loop
{ $$ = $1; }
| stmt_while
{ $$ = $1; }
| stmt_fori
{ $$ = $1; }
| stmt_fors
{ $$ = $1; }
| stmt_select
{ $$ = $1; }
| stmt_exit
{ $$ = $1; }
| stmt_return
{ $$ = $1; }
| stmt_raise
{ $$ = $1; }
| stmt_execsql
{ $$ = $1; }
| stmt_dynexecute
{ $$ = $1; }
| stmt_dynfors
{ $$ = $1; }
| stmt_perform
{ $$ = $1; }
| stmt_getdiag
{ $$ = $1; }
;
stmt_perform : K_PERFORM lno expr_until_semi
{
PLpgSQL_stmt_assign *new;
{
PLpgSQL_stmt_assign *new;
new = malloc(sizeof(PLpgSQL_stmt_assign));
memset(new, 0, sizeof(PLpgSQL_stmt_assign));
new = malloc(sizeof(PLpgSQL_stmt_assign));
memset(new, 0, sizeof(PLpgSQL_stmt_assign));
new->cmd_type = PLPGSQL_STMT_ASSIGN;
new->lineno = $2;
new->varno = -1;
new->expr = $3;
new->cmd_type = PLPGSQL_STMT_ASSIGN;
new->lineno = $2;
new->varno = -1;
new->expr = $3;
$$ = (PLpgSQL_stmt *)new;
}
;
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_assign : assign_var lno K_ASSIGN expr_until_semi
{
PLpgSQL_stmt_assign *new;
stmt_assign : assign_var lno K_ASSIGN expr_until_semi
{
PLpgSQL_stmt_assign *new;
new = malloc(sizeof(PLpgSQL_stmt_assign));
memset(new, 0, sizeof(PLpgSQL_stmt_assign));
new = malloc(sizeof(PLpgSQL_stmt_assign));
memset(new, 0, sizeof(PLpgSQL_stmt_assign));
new->cmd_type = PLPGSQL_STMT_ASSIGN;
new->lineno = $2;
new->varno = $1;
new->expr = $4;
new->cmd_type = PLPGSQL_STMT_ASSIGN;
new->lineno = $2;
new->varno = $1;
new->expr = $4;
$$ = (PLpgSQL_stmt *)new;
}
;
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_getdiag : K_GET K_DIAGNOSTICS lno K_SELECT getdiag_items K_INTO getdiag_targets ';'
{
PLpgSQL_stmt_getdiag *new;
new = malloc(sizeof(PLpgSQL_stmt_getdiag));
memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
new->cmd_type = PLPGSQL_STMT_GETDIAG;
new->lineno = $3;
new->nitems = $5.nused;
new->items = malloc(sizeof(int) * $5.nused);
new->ntargets = $7.nused;
new->targets = malloc(sizeof(int) * $7.nused);
memcpy(new->items, $5.dtnums, sizeof(int) * $5.nused);
memcpy(new->targets, $7.dtnums, sizeof(int) * $7.nused);
if (new->nitems != new->ntargets) {
plpgsql_error_lineno = new->lineno;
plpgsql_comperrinfo();
elog(ERROR, "number of diagnostic items does not match target list");
};
$$ = (PLpgSQL_stmt *)new;
}
;
{
PLpgSQL_stmt_getdiag *new;
new = malloc(sizeof(PLpgSQL_stmt_getdiag));
memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
new->cmd_type = PLPGSQL_STMT_GETDIAG;
new->lineno = $3;
new->nitems = $5.nused;
new->items = malloc(sizeof(int) * $5.nused);
new->ntargets = $7.nused;
new->targets = malloc(sizeof(int) * $7.nused);
memcpy(new->items, $5.dtnums, sizeof(int) * $5.nused);
memcpy(new->targets, $7.dtnums, sizeof(int) * $7.nused);
if (new->nitems != new->ntargets) {
plpgsql_error_lineno = new->lineno;
plpgsql_comperrinfo();
elog(ERROR, "number of diagnostic items does not match target list");
};
$$ = (PLpgSQL_stmt *)new;
}
;
getdiag_items : getdiag_items ',' getdiag_item
{
if ($1.nused == $1.nalloc) {
$1.nalloc *= 2;
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
}
$1.dtnums[$1.nused++] = $3;
$$.nalloc = $1.nalloc;
$$.nused = $1.nused;
$$.dtnums = $1.dtnums;
}
| getdiag_item
{
$$.nalloc = 1;
$$.nused = 1;
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums[0] = $1;
}
;
{
if ($1.nused == $1.nalloc) {
$1.nalloc *= 2;
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
}
$1.dtnums[$1.nused++] = $3;
$$.nalloc = $1.nalloc;
$$.nused = $1.nused;
$$.dtnums = $1.dtnums;
}
| getdiag_item
{
$$.nalloc = 1;
$$.nused = 1;
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums[0] = $1;
}
;
getdiag_item : K_PROCESSED
{
$$ = PLPGSQL_GETDIAG_PROCESSED;
}
| K_RESULT
{
$$ = PLPGSQL_GETDIAG_RESULT;
}
;
{
$$ = PLPGSQL_GETDIAG_PROCESSED;
}
| K_RESULT
{
$$ = PLPGSQL_GETDIAG_RESULT;
}
;
getdiag_targets : getdiag_targets ',' getdiag_target
{
if ($1.nused == $1.nalloc) {
$1.nalloc *= 2;
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
}
$1.dtnums[$1.nused++] = $3;
$$.nalloc = $1.nalloc;
$$.nused = $1.nused;
$$.dtnums = $1.dtnums;
}
| getdiag_target
{
$$.nalloc = 1;
$$.nused = 1;
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums[0] = $1;
}
;
getdiag_target : T_VARIABLE
{
if (yylval.var->isconst) {
plpgsql_comperrinfo();
elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname);
}
$$ = yylval.var->varno;
}
| T_RECFIELD
{
$$ = yylval.recfield->rfno;
}
;
assign_var : T_VARIABLE
{
if (yylval.var->isconst) {
plpgsql_comperrinfo();
elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
}
$$ = yylval.var->varno;
}
| T_RECFIELD
{
$$ = yylval.recfield->rfno;
}
;
stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
{
PLpgSQL_stmt_if *new;
new = malloc(sizeof(PLpgSQL_stmt_if));
memset(new, 0, sizeof(PLpgSQL_stmt_if));
new->cmd_type = PLPGSQL_STMT_IF;
new->lineno = $2;
new->cond = $3;
new->true_body = $4;
new->false_body = $5;
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_else :
{
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
$$ = new;
}
| K_ELSE proc_sect
{ $$ = $2; }
;
stmt_loop : opt_label K_LOOP lno loop_body
{
PLpgSQL_stmt_loop *new;
new = malloc(sizeof(PLpgSQL_stmt_loop));
memset(new, 0, sizeof(PLpgSQL_stmt_loop));
new->cmd_type = PLPGSQL_STMT_LOOP;
new->lineno = $3;
new->label = $1;
new->body = $4;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
{
PLpgSQL_stmt_while *new;
new = malloc(sizeof(PLpgSQL_stmt_while));
memset(new, 0, sizeof(PLpgSQL_stmt_while));
new->cmd_type = PLPGSQL_STMT_WHILE;
new->lineno = $3;
new->label = $1;
new->cond = $4;
new->body = $5;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
;
{
if ($1.nused == $1.nalloc) {
$1.nalloc *= 2;
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
}
$1.dtnums[$1.nused++] = $3;
$$.nalloc = $1.nalloc;
$$.nused = $1.nused;
$$.dtnums = $1.dtnums;
}
| getdiag_target
{
$$.nalloc = 1;
$$.nused = 1;
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums[0] = $1;
}
;
getdiag_target : T_VARIABLE
{
if (yylval.var->isconst) {
plpgsql_comperrinfo();
elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname);
}
$$ = yylval.var->varno;
}
| T_RECFIELD
{
$$ = yylval.recfield->rfno;
}
;
assign_var : T_VARIABLE
{
if (yylval.var->isconst) {
plpgsql_comperrinfo();
elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
}
$$ = yylval.var->varno;
}
| T_RECFIELD
{
$$ = yylval.recfield->rfno;
}
;
stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
{
PLpgSQL_stmt_if *new;
new = malloc(sizeof(PLpgSQL_stmt_if));
memset(new, 0, sizeof(PLpgSQL_stmt_if));
new->cmd_type = PLPGSQL_STMT_IF;
new->lineno = $2;
new->cond = $3;
new->true_body = $4;
new->false_body = $5;
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_else :
{
PLpgSQL_stmts *new;
new = malloc(sizeof(PLpgSQL_stmts));
memset(new, 0, sizeof(PLpgSQL_stmts));
$$ = new;
}
| K_ELSE proc_sect
{ $$ = $2; }
;
stmt_loop : opt_label K_LOOP lno loop_body
{
PLpgSQL_stmt_loop *new;
new = malloc(sizeof(PLpgSQL_stmt_loop));
memset(new, 0, sizeof(PLpgSQL_stmt_loop));
new->cmd_type = PLPGSQL_STMT_LOOP;
new->lineno = $3;
new->label = $1;
new->body = $4;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
{
PLpgSQL_stmt_while *new;
new = malloc(sizeof(PLpgSQL_stmt_while));
memset(new, 0, sizeof(PLpgSQL_stmt_while));
new->cmd_type = PLPGSQL_STMT_WHILE;
new->lineno = $3;
new->label = $1;
new->cond = $4;
new->body = $5;
plpgsql_ns_pop();
$$ = (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
{
PLpgSQL_stmt_fori *new;
new->dtype = PLPGSQL_DTYPE_VAR;
new->refname = $1.name;
new->lineno = $1.lineno;
new = malloc(sizeof(PLpgSQL_stmt_fori));
memset(new, 0, sizeof(PLpgSQL_stmt_fori));
plpgsql_parse_word("integer");
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;
new->datatype = yylval.dtype;
new->isconst = false;
new->notnull = false;
new->default_val = NULL;
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
{
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;
}
;
$$ = new;
}
;
fori_varname : T_VARIABLE
{
$$.name = strdup(yytext);
$$.lineno = yylineno;
}
| T_WORD
{
$$.name = strdup(yytext);
$$.lineno = yylineno;
}
;
fori_lower :
{
int tok;
int lno;
PLpgSQL_dstring ds;
int nparams = 0;
int params[1024];
char buf[32];
PLpgSQL_expr *expr;
int firsttok = 1;
lno = yylineno;
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
$$.reverse = 0;
while((tok = yylex()) != K_DOTDOT) {
if (firsttok) {
firsttok = 0;
if (tok == K_REVERSE) {
$$.reverse = 1;
continue;
}
}
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 .. to terminate lower bound of for loop");
}
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);
$$.expr = expr;
}
stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
{
PLpgSQL_stmt_fors *new;
new = malloc(sizeof(PLpgSQL_stmt_fors));
memset(new, 0, sizeof(PLpgSQL_stmt_fors));
new->cmd_type = PLPGSQL_STMT_FORS;
new->lineno = $3;
new->label = $1;
switch ($4->dtype) {
case PLPGSQL_DTYPE_REC:
new->rec = $4;
break;
case PLPGSQL_DTYPE_ROW:
new->row = (PLpgSQL_row *)$4;
break;
default:
plpgsql_comperrinfo();
elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
}
new->query = $7;
new->body = $8;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
{
$$.name = strdup(yytext);
$$.lineno = yylineno;
}
| T_WORD
{
$$.name = strdup(yytext);
$$.lineno = yylineno;
}
;
fori_lower :
{
int tok;
int lno;
PLpgSQL_dstring ds;
int nparams = 0;
int params[1024];
char buf[32];
PLpgSQL_expr *expr;
int firsttok = 1;
lno = yylineno;
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
$$.reverse = 0;
while((tok = yylex()) != K_DOTDOT) {
if (firsttok) {
firsttok = 0;
if (tok == K_REVERSE) {
$$.reverse = 1;
continue;
}
}
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 .. to terminate lower bound of for loop");
}
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);
$$.expr = expr;
}
stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
{
PLpgSQL_stmt_fors *new;
new = malloc(sizeof(PLpgSQL_stmt_fors));
memset(new, 0, sizeof(PLpgSQL_stmt_fors));
new->cmd_type = PLPGSQL_STMT_FORS;
new->lineno = $3;
new->label = $1;
switch ($4->dtype) {
case PLPGSQL_DTYPE_REC:
new->rec = $4;
break;
case PLPGSQL_DTYPE_ROW:
new->row = (PLpgSQL_row *)$4;
break;
default:
plpgsql_comperrinfo();
elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
}
new->query = $7;
new->body = $8;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body
{
PLpgSQL_stmt_dynfors *new;
new = malloc(sizeof(PLpgSQL_stmt_dynfors));
memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
new->cmd_type = PLPGSQL_STMT_DYNFORS;
new->lineno = $3;
new->label = $1;
switch ($4->dtype) {
case PLPGSQL_DTYPE_REC:
new->rec = $4;
break;
case PLPGSQL_DTYPE_ROW:
new->row = (PLpgSQL_row *)$4;
break;
default:
plpgsql_comperrinfo();
elog(ERROR, "unknown dtype %d in stmt_dynfors", $4->dtype);
}
new->query = $7;
new->body = $8;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
fors_target : T_RECORD
{
$$ = yylval.rec;
}
| T_ROW
{
$$ = (PLpgSQL_rec *)(yylval.row);
}
;
stmt_select : K_SELECT lno
{
$$ = make_select_stmt();
$$->lineno = $2;
}
;
stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
{
PLpgSQL_stmt_exit *new;
new = malloc(sizeof(PLpgSQL_stmt_exit));
memset(new, 0, sizeof(PLpgSQL_stmt_exit));
new->cmd_type = PLPGSQL_STMT_EXIT;
new->lineno = $2;
new->label = $3;
new->cond = $4;
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_return : K_RETURN lno
{
PLpgSQL_stmt_return *new;
PLpgSQL_expr *expr = NULL;
int tok;
new = malloc(sizeof(PLpgSQL_stmt_return));
memset(new, 0, sizeof(PLpgSQL_stmt_return));
if (plpgsql_curr_compile->fn_retistuple) {
new->retistuple = true;
new->retrecno = -1;
switch (tok = yylex()) {
case K_NULL:
expr = NULL;
break;
case T_ROW:
expr = make_tupret_expr(yylval.row);
break;
case T_RECORD:
new->retrecno = yylval.rec->recno;
expr = NULL;
break;
default:
yyerror("return type mismatch in function returning table row");
break;
}
if (yylex() != ';') {
yyerror("expected ';'");
}
} else {
new->retistuple = false;
expr = plpgsql_read_expression(';', ";");
}
new->cmd_type = PLPGSQL_STMT_RETURN;
new->lineno = $2;
new->expr = expr;
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
{
PLpgSQL_stmt_raise *new;
new = malloc(sizeof(PLpgSQL_stmt_raise));
new->cmd_type = PLPGSQL_STMT_RAISE;
new->lineno = $2;
new->elog_level = $3;
new->message = $4;
new->nparams = $5.nused;
new->params = malloc(sizeof(int) * $5.nused);
memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused);
$$ = (PLpgSQL_stmt *)new;
}
| K_RAISE lno raise_level raise_msg ';'
{
PLpgSQL_stmt_raise *new;
new = malloc(sizeof(PLpgSQL_stmt_raise));
new->cmd_type = PLPGSQL_STMT_RAISE;
new->lineno = $2;
new->elog_level = $3;
new->message = $4;
new->nparams = 0;
new->params = NULL;
$$ = (PLpgSQL_stmt *)new;
}
;
raise_msg : T_STRING
{
$$ = strdup(yytext);
}
;
raise_level : K_EXCEPTION
{
$$ = ERROR;
}
| K_NOTICE
{
$$ = NOTICE;
}
| K_DEBUG
{
$$ = DEBUG;
}
;
{
PLpgSQL_stmt_dynfors *new;
new = malloc(sizeof(PLpgSQL_stmt_dynfors));
memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
new->cmd_type = PLPGSQL_STMT_DYNFORS;
new->lineno = $3;
new->label = $1;
switch ($4->dtype) {
case PLPGSQL_DTYPE_REC:
new->rec = $4;
break;
case PLPGSQL_DTYPE_ROW:
new->row = (PLpgSQL_row *)$4;
break;
default:
plpgsql_comperrinfo();
elog(ERROR, "unknown dtype %d in stmt_dynfors", $4->dtype);
}
new->query = $7;
new->body = $8;
plpgsql_ns_pop();
$$ = (PLpgSQL_stmt *)new;
}
fors_target : T_RECORD
{
$$ = yylval.rec;
}
| T_ROW
{
$$ = (PLpgSQL_rec *)(yylval.row);
}
;
stmt_select : K_SELECT lno
{
$$ = make_select_stmt();
$$->lineno = $2;
}
;
stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
{
PLpgSQL_stmt_exit *new;
new = malloc(sizeof(PLpgSQL_stmt_exit));
memset(new, 0, sizeof(PLpgSQL_stmt_exit));
new->cmd_type = PLPGSQL_STMT_EXIT;
new->lineno = $2;
new->label = $3;
new->cond = $4;
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_return : K_RETURN lno
{
PLpgSQL_stmt_return *new;
PLpgSQL_expr *expr = NULL;
int tok;
new = malloc(sizeof(PLpgSQL_stmt_return));
memset(new, 0, sizeof(PLpgSQL_stmt_return));
if (plpgsql_curr_compile->fn_retistuple) {
new->retistuple = true;
new->retrecno = -1;
switch (tok = yylex()) {
case K_NULL:
expr = NULL;
break;
case T_ROW:
expr = make_tupret_expr(yylval.row);
break;
case T_RECORD:
new->retrecno = yylval.rec->recno;
expr = NULL;
break;
default:
yyerror("return type mismatch in function returning table row");
break;
}
if (yylex() != ';') {
yyerror("expected ';'");
}
} else {
new->retistuple = false;
expr = plpgsql_read_expression(';', ";");
}
new->cmd_type = PLPGSQL_STMT_RETURN;
new->lineno = $2;
new->expr = expr;
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
{
PLpgSQL_stmt_raise *new;
new = malloc(sizeof(PLpgSQL_stmt_raise));
new->cmd_type = PLPGSQL_STMT_RAISE;
new->lineno = $2;
new->elog_level = $3;
new->message = $4;
new->nparams = $5.nused;
new->params = malloc(sizeof(int) * $5.nused);
memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused);
$$ = (PLpgSQL_stmt *)new;
}
| K_RAISE lno raise_level raise_msg ';'
{
PLpgSQL_stmt_raise *new;
new = malloc(sizeof(PLpgSQL_stmt_raise));
new->cmd_type = PLPGSQL_STMT_RAISE;
new->lineno = $2;
new->elog_level = $3;
new->message = $4;
new->nparams = 0;
new->params = NULL;
$$ = (PLpgSQL_stmt *)new;
}
;
raise_msg : T_STRING
{
$$ = strdup(yytext);
}
;
raise_level : K_EXCEPTION
{
$$ = ERROR;
}
| K_NOTICE
{
$$ = NOTICE;
}
| K_DEBUG
{
$$ = DEBUG;
}
;
raise_params : raise_params raise_param
{
if ($1.nused == $1.nalloc) {
$1.nalloc *= 2;
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
}
$1.dtnums[$1.nused++] = $2;
$$.nalloc = $1.nalloc;
$$.nused = $1.nused;
$$.dtnums = $1.dtnums;
}
| raise_param
{
$$.nalloc = 1;
$$.nused = 1;
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums[0] = $1;
}
;
raise_param : ',' T_VARIABLE
{
$$ = yylval.var->varno;
}
| ',' T_RECFIELD
{
$$ = yylval.recfield->rfno;
}
| ',' T_TGARGV
{
$$ = yylval.trigarg->dno;
}
;
loop_body : proc_sect K_END K_LOOP ';'
{ $$ = $1; }
;
{
if ($1.nused == $1.nalloc) {
$1.nalloc *= 2;
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
}
$1.dtnums[$1.nused++] = $2;
$$.nalloc = $1.nalloc;
$$.nused = $1.nused;
$$.dtnums = $1.dtnums;
}
| raise_param
{
$$.nalloc = 1;
$$.nused = 1;
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
$$.dtnums[0] = $1;
}
;
raise_param : ',' T_VARIABLE
{
$$ = yylval.var->varno;
}
| ',' T_RECFIELD
{
$$ = yylval.recfield->rfno;
}
| ',' T_TGARGV
{
$$ = yylval.trigarg->dno;
}
;
loop_body : proc_sect K_END K_LOOP ';'
{ $$ = $1; }
;
stmt_execsql : execsql_start lno
{
PLpgSQL_stmt_execsql *new;
{
PLpgSQL_stmt_execsql *new;
new = malloc(sizeof(PLpgSQL_stmt_execsql));
new->cmd_type = PLPGSQL_STMT_EXECSQL;
new->lineno = $2;
new->sqlstmt = read_sqlstmt(';', ";", $1);
new = malloc(sizeof(PLpgSQL_stmt_execsql));
new->cmd_type = PLPGSQL_STMT_EXECSQL;
new->lineno = $2;
new->sqlstmt = read_sqlstmt(';', ";", $1);
$$ = (PLpgSQL_stmt *)new;
}
;
$$ = (PLpgSQL_stmt *)new;
}
;
stmt_dynexecute : K_EXECUTE lno expr_until_semi
{
PLpgSQL_stmt_dynexecute *new;
stmt_dynexecute : K_EXECUTE lno expr_until_semi
{
PLpgSQL_stmt_dynexecute *new;
new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
new->lineno = $2;
new->query = $3;
new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
new->lineno = $2;
new->query = $3;
$$ = (PLpgSQL_stmt *)new;
}
;
$$ = (PLpgSQL_stmt *)new;
}
;
execsql_start : T_WORD
{ $$ = strdup(yytext); }
| T_ERROR
{ $$ = strdup(yytext); }
;
expr_until_semi :
{ $$ = plpgsql_read_expression(';', ";"); }
;
expr_until_then :
{ $$ = plpgsql_read_expression(K_THEN, "THEN"); }
;
expr_until_loop :
{ $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
;
opt_label :
{
plpgsql_ns_push(NULL);
$$ = NULL;
}
| '<' '<' opt_lblname '>' '>'
{
plpgsql_ns_push($3);
$$ = $3;
}
;
{ $$ = strdup(yytext); }
| T_ERROR
{ $$ = strdup(yytext); }
;
expr_until_semi :
{ $$ = plpgsql_read_expression(';', ";"); }
;
expr_until_then :
{ $$ = plpgsql_read_expression(K_THEN, "THEN"); }
;
expr_until_loop :
{ $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
;
opt_label :
{
plpgsql_ns_push(NULL);
$$ = NULL;
}
| '<' '<' opt_lblname '>' '>'
{
plpgsql_ns_push($3);
$$ = $3;
}
;
opt_exitlabel :
{ $$ = NULL; }
| T_LABEL
{ $$ = strdup(yytext); }
;
{ $$ = NULL; }
| T_LABEL
{ $$ = strdup(yytext); }
;
opt_exitcond : ';'
{ $$ = NULL; }
| K_WHEN expr_until_semi
{ $$ = $2; }
;
opt_lblname : T_WORD
{ $$ = strdup(yytext); }
;
lno :
{
plpgsql_error_lineno = yylineno;
$$ = yylineno;
}
;
{ $$ = NULL; }
| K_WHEN expr_until_semi
{ $$ = $2; }
;
opt_lblname : T_WORD
{ $$ = strdup(yytext); }
;
lno :
{
plpgsql_error_lineno = yylineno;
$$ = yylineno;
}
;
%%
......@@ -1244,237 +1244,104 @@ lno :
PLpgSQL_expr *
plpgsql_read_expression (int until, char *s)
{
return read_sqlstmt(until, s, "SELECT ");
return read_sqlstmt(until, s, "SELECT ");
}
static PLpgSQL_expr *
read_sqlstmt (int until, char *s, char *sqlstart)
{
int tok;
int lno;
PLpgSQL_dstring ds;
int nparams = 0;
int params[1024];
char buf[32];
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);
int tok;
int lno;
PLpgSQL_dstring ds;
int nparams = 0;
int params[1024];
char buf[32];
PLpgSQL_expr *expr;
execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
execsql->sqlstmt = expr;
lno = yylineno;
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, sqlstart);
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");
while((tok = yylex()) != until) {
if (tok == ';') break;
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
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) {
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:
var = yylval.var;
fieldnames[nfields] = strdup(yytext);
varnos[nfields++] = var->varno;
break;
params[nparams] = yylval.var->varno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
case T_RECFIELD:
recfield = yylval.recfield;
fieldnames[0] = strdup(yytext);
varnos[0] = recfield->rfno;
break;
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:
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];
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;
}
}
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;
}
break;
return expr;
}
default:
{
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
plpgsql_dstring_append(&ds, yytext);
while(1) {
tok = yylex();
if (tok == ';') {
PLpgSQL_stmt_execsql *execsql;
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;
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];
expr->params[nparams] = params[nparams];
}
plpgsql_dstring_free(&ds);
......@@ -1483,134 +1350,267 @@ make_select_stmt()
execsql->sqlstmt = expr;
return (PLpgSQL_stmt *)execsql;
}
}
if (plpgsql_SpaceScanned) {
if (plpgsql_SpaceScanned) {
plpgsql_dstring_append(&ds, " ");
}
switch (tok) {
}
switch (tok) {
case T_VARIABLE:
params[nparams] = yylval.var->varno;
sprintf(buf, " $%d ", ++nparams);
plpgsql_dstring_append(&ds, buf);
break;
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;
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;
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;
}
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, " ");
}
tok = yylex();
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");
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) {
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:
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->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);
select = malloc(sizeof(PLpgSQL_stmt_select));
memset(select, 0, sizeof(PLpgSQL_stmt_select));
select->cmd_type = PLPGSQL_STMT_SELECT;
select->rec = rec;
select->row = row;
select->query = expr;
return (PLpgSQL_stmt *)select;
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);
select = malloc(sizeof(PLpgSQL_stmt_select));
memset(select, 0, sizeof(PLpgSQL_stmt_select));
select->cmd_type = PLPGSQL_STMT_SELECT;
select->rec = rec;
select->row = row;
select->query = expr;
return (PLpgSQL_stmt *)select;
}
static PLpgSQL_expr *
make_tupret_expr(PLpgSQL_row *row)
{
PLpgSQL_dstring ds;
PLpgSQL_expr *expr;
int i;
char buf[16];
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
expr->dtype = PLPGSQL_DTYPE_EXPR;
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
for (i = 0; i < row->nfields; i++) {
sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
plpgsql_dstring_append(&ds, buf);
expr->params[i] = row->varnos[i];
}
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->plan = NULL;
expr->plan_argtypes = NULL;
expr->nparams = row->nfields;
plpgsql_dstring_free(&ds);
return expr;
PLpgSQL_dstring ds;
PLpgSQL_expr *expr;
int i;
char buf[16];
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
expr->dtype = PLPGSQL_DTYPE_EXPR;
plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds, "SELECT ");
for (i = 0; i < row->nfields; i++) {
sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
plpgsql_dstring_append(&ds, buf);
expr->params[i] = row->varnos[i];
}
expr->query = strdup(plpgsql_dstring_get(&ds));
expr->plan = NULL;
expr->plan_argtypes = NULL;
expr->nparams = row->nfields;
plpgsql_dstring_free(&ds);
return expr;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment