%{
/**********************************************************************
- * 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.
*
**********************************************************************/
%}
%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
%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
%token K_NOTICE
%token K_NULL
%token K_PERFORM
-%token K_PROCESSED
+%token K_PROCESSED
%token K_RAISE
%token K_RECORD
%token K_RENAME
%token K_WHEN
%token K_WHILE
- /*
- * Other tokens
- */
+ /*
+ * Other tokens
+ */
%token T_FUNCTION
%token T_TRIGGER
%token T_CHAR
%%
-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;
+ }
+ ;
%%
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);
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;
}