From b54073ea4c6feee6735fe9f655bd9807d4a66179 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sat, 10 Feb 2001 22:42:01 +0000 Subject: [PATCH] Convert to standard 4-space tabs. --- src/pl/plpgsql/src/gram.y | 2750 ++++++++++++++++++++++----------------------- 1 file changed, 1375 insertions(+), 1375 deletions(-) diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index ed1704276e..80580de501 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -1,38 +1,38 @@ %{ /********************************************************************** - * 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 decl_sect -%type decl_varname -%type decl_renname +%type decl_sect +%type decl_varname +%type decl_renname %type decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval %type decl_defval %type decl_datatype, decl_dtypename -%type decl_rowtype +%type decl_rowtype %type decl_aliasitem -%type decl_stmts, decl_stmt +%type decl_stmts, decl_stmt %type expr_until_semi, expr_until_then, expr_until_loop %type opt_exitcond %type assign_var -%type fori_var -%type fori_varname -%type fori_lower -%type fors_target +%type fori_var +%type fori_varname +%type fori_lower +%type fors_target -%type opt_lblname, opt_label -%type opt_exitlabel -%type execsql_start +%type opt_lblname, opt_label +%type opt_exitlabel +%type execsql_start %type proc_sect, proc_stmts, stmt_else, loop_body %type proc_stmt, pl_block @@ -117,16 +117,16 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row); %type raise_params %type raise_level, raise_param -%type raise_msg +%type raise_msg %type getdiag_items, getdiag_targets %type getdiag_item, getdiag_target %type 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; } -- 2.11.0