]> granicus.if.org Git - postgresql/blob - src/pl/plpgsql/src/gram.y
dd15cf80a2f83f6dd5a944940b54a163c686fa84
[postgresql] / src / pl / plpgsql / src / gram.y
1 %{
2 /**********************************************************************
3  * gram.y                               - Parser for the PL/pgSQL
4  *                                                procedural language
5  *
6  * IDENTIFICATION
7  *        $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.42 2003/04/27 22:21:22 tgl Exp $
8  *
9  *        This software is copyrighted by Jan Wieck - Hamburg.
10  *
11  *        The author hereby grants permission  to  use,  copy,  modify,
12  *        distribute,  and      license this software and its documentation
13  *        for any purpose, provided that existing copyright notices are
14  *        retained      in      all  copies  and  that  this notice is included
15  *        verbatim in any distributions. No written agreement, license,
16  *        or  royalty  fee      is required for any of the authorized uses.
17  *        Modifications to this software may be  copyrighted  by  their
18  *        author  and  need  not  follow  the licensing terms described
19  *        here, provided that the new terms are  clearly  indicated  on
20  *        the first page of each file where they apply.
21  *
22  *        IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
23  *        PARTY  FOR  DIRECT,   INDIRECT,       SPECIAL,   INCIDENTAL,   OR
24  *        CONSEQUENTIAL   DAMAGES  ARISING      OUT  OF  THE  USE  OF  THIS
25  *        SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
26  *        IF  THE  AUTHOR  HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
27  *        DAMAGE.
28  *
29  *        THE  AUTHOR  AND      DISTRIBUTORS  SPECIFICALLY       DISCLAIM       ANY
30  *        WARRANTIES,  INCLUDING,  BUT  NOT  LIMITED  TO,  THE  IMPLIED
31  *        WARRANTIES  OF  MERCHANTABILITY,      FITNESS  FOR  A  PARTICULAR
32  *        PURPOSE,      AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON
33  *        AN "AS IS" BASIS, AND THE AUTHOR      AND  DISTRIBUTORS  HAVE  NO
34  *        OBLIGATION   TO       PROVIDE   MAINTENANCE,   SUPPORT,  UPDATES,
35  *        ENHANCEMENTS, OR MODIFICATIONS.
36  *
37  **********************************************************************/
38
39 #include "plpgsql.h"
40
41
42 static  PLpgSQL_expr    *read_sql_construct(int until,
43                                                                                         const char *expected,
44                                                                                         bool isexpression,
45                                                                                         const char *sqlstart);
46 static  PLpgSQL_expr    *read_sql_stmt(const char *sqlstart);
47 static  PLpgSQL_type    *read_datatype(int tok);
48 static  PLpgSQL_stmt    *make_select_stmt(void);
49 static  PLpgSQL_stmt    *make_fetch_stmt(void);
50 static  PLpgSQL_expr    *make_tupret_expr(PLpgSQL_row *row);
51 static  void check_assignable(PLpgSQL_datum *datum);
52
53 %}
54
55 %union {
56                 int32                                   ival;
57                 char                                    *str;
58                 struct
59                 {
60                         char *name;
61                         int  lineno;
62                 }                                               varname;
63                 struct
64                 {
65                         int  nalloc;
66                         int  nused;
67                         int      *nums;
68                 }                                               intlist;
69                 struct
70                 {
71                         int  nalloc;
72                         int  nused;
73                         PLpgSQL_diag_item *dtitems;
74                 }                                               dtlist;
75                 struct
76                 {
77                         int  reverse;
78                         PLpgSQL_expr *expr;
79                 }                                               forilow;
80                 struct
81                 {
82                         char *label;
83                         int  n_initvars;
84                         int  *initvarnos;
85                 }                                               declhdr;
86                 PLpgSQL_type                    *dtype;
87                 PLpgSQL_datum                   *variable; /* a VAR, RECFIELD, or TRIGARG */
88                 PLpgSQL_var                             *var;
89                 PLpgSQL_row                             *row;
90                 PLpgSQL_rec                             *rec;
91                 PLpgSQL_expr                    *expr;
92                 PLpgSQL_stmt                    *stmt;
93                 PLpgSQL_stmts                   *stmts;
94                 PLpgSQL_stmt_block              *program;
95                 PLpgSQL_nsitem                  *nsitem;
96 }
97
98 %type <declhdr> decl_sect
99 %type <varname> decl_varname
100 %type <str>             decl_renname
101 %type <ival>    decl_const decl_notnull
102 %type <expr>    decl_defval decl_cursor_query
103 %type <dtype>   decl_datatype
104 %type <row>             decl_rowtype decl_cursor_args decl_cursor_arglist
105 %type <nsitem>  decl_aliasitem
106 %type <str>             decl_stmts decl_stmt
107
108 %type <expr>    expr_until_semi expr_until_rightbracket
109 %type <expr>    expr_until_then expr_until_loop
110 %type <expr>    opt_exitcond
111
112 %type <ival>    assign_var cursor_variable
113 %type <var>             fori_var cursor_varptr decl_cursor_arg
114 %type <varname> fori_varname
115 %type <forilow> fori_lower
116 %type <rec>             fors_target
117
118 %type <str>             opt_lblname opt_label
119 %type <str>             opt_exitlabel
120 %type <str>             execsql_start
121
122 %type <stmts>   proc_sect proc_stmts stmt_else loop_body
123 %type <stmt>    proc_stmt pl_block
124 %type <stmt>    stmt_assign stmt_if stmt_loop stmt_while stmt_exit
125 %type <stmt>    stmt_return stmt_return_next stmt_raise stmt_execsql
126 %type <stmt>    stmt_fori stmt_fors stmt_select stmt_perform
127 %type <stmt>    stmt_dynexecute stmt_dynfors stmt_getdiag
128 %type <stmt>    stmt_open stmt_fetch stmt_close
129
130 %type <intlist> raise_params
131 %type <ival>    raise_level raise_param
132 %type <str>             raise_msg
133
134 %type <dtlist>  getdiag_list
135 %type <ival>    getdiag_item getdiag_target
136
137 %type <ival>    lno
138
139                 /*
140                  * Keyword tokens
141                  */
142 %token  K_ALIAS
143 %token  K_ASSIGN
144 %token  K_BEGIN
145 %token  K_CLOSE
146 %token  K_CONSTANT
147 %token  K_CURSOR
148 %token  K_DEBUG
149 %token  K_DECLARE
150 %token  K_DEFAULT
151 %token  K_DIAGNOSTICS
152 %token  K_DOTDOT
153 %token  K_ELSE
154 %token  K_ELSIF
155 %token  K_END
156 %token  K_EXCEPTION
157 %token  K_EXECUTE
158 %token  K_EXIT
159 %token  K_FOR
160 %token  K_FETCH
161 %token  K_FROM
162 %token  K_GET
163 %token  K_IF
164 %token  K_IN
165 %token  K_INFO
166 %token  K_INTO
167 %token  K_IS
168 %token  K_LOG
169 %token  K_LOOP
170 %token  K_NEXT
171 %token  K_NOT
172 %token  K_NOTICE
173 %token  K_NULL
174 %token  K_OPEN
175 %token  K_PERFORM
176 %token  K_ROW_COUNT
177 %token  K_RAISE
178 %token  K_RECORD
179 %token  K_RENAME
180 %token  K_RESULT_OID
181 %token  K_RETURN
182 %token  K_RETURN_NEXT
183 %token  K_REVERSE
184 %token  K_SELECT
185 %token  K_THEN
186 %token  K_TO
187 %token  K_TYPE
188 %token  K_WARNING
189 %token  K_WHEN
190 %token  K_WHILE
191
192                 /*
193                  * Other tokens
194                  */
195 %token  T_FUNCTION
196 %token  T_TRIGGER
197 %token  T_STRING
198 %token  T_NUMBER
199 %token  T_VARIABLE                              /* a VAR, RECFIELD, or TRIGARG */
200 %token  T_ROW
201 %token  T_RECORD
202 %token  T_DTYPE
203 %token  T_LABEL
204 %token  T_WORD
205 %token  T_ERROR
206
207 %token  O_OPTION
208 %token  O_DUMP
209
210 %%
211
212 pl_function             : T_FUNCTION comp_optsect pl_block opt_semi
213                                         {
214                                                 yylval.program = (PLpgSQL_stmt_block *)$3;
215                                         }
216                                 | T_TRIGGER comp_optsect pl_block opt_semi
217                                         {
218                                                 yylval.program = (PLpgSQL_stmt_block *)$3;
219                                         }
220                                 ;
221
222 comp_optsect    :
223                                 | comp_options
224                                 ;
225
226 comp_options    : comp_options comp_option
227                                 | comp_option
228                                 ;
229
230 comp_option             : O_OPTION O_DUMP
231                                         {
232                                                 plpgsql_DumpExecTree = 1;
233                                         }
234                                 ;
235
236 opt_semi                :
237                                 | ';'
238                                 ;
239
240 pl_block                : decl_sect K_BEGIN lno proc_sect K_END
241                                         {
242                                                 PLpgSQL_stmt_block *new;
243
244                                                 new = malloc(sizeof(PLpgSQL_stmt_block));
245                                                 memset(new, 0, sizeof(PLpgSQL_stmt_block));
246
247                                                 new->cmd_type   = PLPGSQL_STMT_BLOCK;
248                                                 new->lineno             = $3;
249                                                 new->label              = $1.label;
250                                                 new->n_initvars = $1.n_initvars;
251                                                 new->initvarnos = $1.initvarnos;
252                                                 new->body               = $4;
253
254                                                 plpgsql_ns_pop();
255
256                                                 $$ = (PLpgSQL_stmt *)new;
257                                         }
258                                 ;
259
260
261 decl_sect               : opt_label
262                                         {
263                                                 plpgsql_ns_setlocal(false);
264                                                 $$.label          = $1;
265                                                 $$.n_initvars = 0;
266                                                 $$.initvarnos = NULL;
267                                                 plpgsql_add_initdatums(NULL);
268                                         }
269                                 | opt_label decl_start
270                                         {
271                                                 plpgsql_ns_setlocal(false);
272                                                 $$.label          = $1;
273                                                 $$.n_initvars = 0;
274                                                 $$.initvarnos = NULL;
275                                                 plpgsql_add_initdatums(NULL);
276                                         }
277                                 | opt_label decl_start decl_stmts
278                                         {
279                                                 plpgsql_ns_setlocal(false);
280                                                 if ($3 != NULL)
281                                                         $$.label = $3;
282                                                 else
283                                                         $$.label = $1;
284                                                 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
285                                         }
286                                 ;
287
288 decl_start              : K_DECLARE
289                                         {
290                                                 plpgsql_ns_setlocal(true);
291                                         }
292                                 ;
293
294 decl_stmts              : decl_stmts decl_stmt
295                                         {       $$ = $2;        }
296                                 | decl_stmt
297                                         {       $$ = $1;        }
298                                 ;
299
300 decl_stmt               : '<' '<' opt_lblname '>' '>'
301                                         {       $$ = $3;        }
302                                 | K_DECLARE
303                                         {       $$ = NULL;      }
304                                 | decl_statement
305                                         {       $$ = NULL;      }
306                                 ;
307
308 decl_statement  : decl_varname decl_const decl_datatype decl_notnull decl_defval
309                                         {
310                                                 if (!OidIsValid($3->typrelid))
311                                                 {
312                                                         /* Ordinary scalar datatype */
313                                                         PLpgSQL_var             *var;
314
315                                                         var = malloc(sizeof(PLpgSQL_var));
316                                                         memset(var, 0, sizeof(PLpgSQL_var));
317
318                                                         var->dtype              = PLPGSQL_DTYPE_VAR;
319                                                         var->refname    = $1.name;
320                                                         var->lineno             = $1.lineno;
321
322                                                         var->datatype   = $3;
323                                                         var->isconst    = $2;
324                                                         var->notnull    = $4;
325                                                         var->default_val = $5;
326
327                                                         plpgsql_adddatum((PLpgSQL_datum *)var);
328                                                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
329                                                                                            var->varno,
330                                                                                            $1.name);
331                                                 }
332                                                 else
333                                                 {
334                                                         /* Composite type --- treat as rowtype */
335                                                         PLpgSQL_row        *row;
336
337                                                         row = build_rowtype($3->typrelid);
338                                                         row->dtype              = PLPGSQL_DTYPE_ROW;
339                                                         row->refname    = $1.name;
340                                                         row->lineno             = $1.lineno;
341
342                                                         if ($2)
343                                                                 elog(ERROR, "Rowtype variable cannot be CONSTANT");
344                                                         if ($4)
345                                                                 elog(ERROR, "Rowtype variable cannot be NOT NULL");
346                                                         if ($5 != NULL)
347                                                                 elog(ERROR, "Default value for rowtype variable is not supported");
348
349                                                         plpgsql_adddatum((PLpgSQL_datum *)row);
350                                                         plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
351                                                                                            row->rowno,
352                                                                                            $1.name);
353
354                                                 }
355                                         }
356                                 | decl_varname K_RECORD ';'
357                                         {
358                                                 PLpgSQL_rec             *var;
359
360                                                 var = malloc(sizeof(PLpgSQL_rec));
361
362                                                 var->dtype              = PLPGSQL_DTYPE_REC;
363                                                 var->refname    = $1.name;
364                                                 var->lineno             = $1.lineno;
365
366                                                 plpgsql_adddatum((PLpgSQL_datum *)var);
367                                                 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, var->recno,
368                                                                                                 $1.name);
369                                         }
370                                 | decl_varname decl_rowtype ';'
371                                         {
372                                                 $2->dtype               = PLPGSQL_DTYPE_ROW;
373                                                 $2->refname             = $1.name;
374                                                 $2->lineno              = $1.lineno;
375
376                                                 plpgsql_adddatum((PLpgSQL_datum *)$2);
377                                                 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
378                                                                                                 $1.name);
379                                         }
380                                 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
381                                         {
382                                                 plpgsql_ns_additem($4->itemtype,
383                                                                                 $4->itemno, $1.name);
384                                         }
385                                 | K_RENAME decl_renname K_TO decl_renname ';'
386                                         {
387                                                 plpgsql_ns_rename($2, $4);
388                                         }
389                                 | decl_varname K_CURSOR
390                                         { plpgsql_ns_push(NULL); }
391                                   decl_cursor_args decl_is_from K_SELECT decl_cursor_query
392                                         {
393                                                 PLpgSQL_var *new;
394                                                 PLpgSQL_expr *curname_def;
395                                                 char            buf[1024];
396                                                 char            *cp1;
397                                                 char            *cp2;
398
399                                                 /* pop local namespace for cursor args */
400                                                 plpgsql_ns_pop();
401
402                                                 new = malloc(sizeof(PLpgSQL_var));
403                                                 memset(new, 0, sizeof(PLpgSQL_var));
404
405                                                 curname_def = malloc(sizeof(PLpgSQL_expr));
406                                                 memset(curname_def, 0, sizeof(PLpgSQL_expr));
407
408                                                 new->dtype              = PLPGSQL_DTYPE_VAR;
409                                                 new->refname    = $1.name;
410                                                 new->lineno             = $1.lineno;
411
412                                                 curname_def->dtype = PLPGSQL_DTYPE_EXPR;
413                                                 strcpy(buf, "SELECT '");
414                                                 cp1 = new->refname;
415                                                 cp2 = buf + strlen(buf);
416                                                 while (*cp1 != '\0')
417                                                 {
418                                                         if (*cp1 == '\\' || *cp1 == '\'')
419                                                                 *cp2++ = '\\';
420                                                         *cp2++ = *cp1++;
421                                                 }
422                                                 strcpy(cp2, "'::refcursor");
423                                                 curname_def->query = strdup(buf);
424                                                 new->default_val = curname_def;
425
426                                                 new->datatype = plpgsql_parse_datatype("refcursor");
427
428                                                 new->cursor_explicit_expr = $7;
429                                                 if ($4 == NULL)
430                                                         new->cursor_explicit_argrow = -1;
431                                                 else
432                                                         new->cursor_explicit_argrow = $4->rowno;
433
434                                                 plpgsql_adddatum((PLpgSQL_datum *)new);
435                                                 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
436                                                                                    $1.name);
437                                         }
438                                 ;
439
440 decl_cursor_query :
441                                         {
442                                                 PLpgSQL_expr *query;
443
444                                                 plpgsql_ns_setlocal(false);
445                                                 query = read_sql_stmt("SELECT ");
446                                                 plpgsql_ns_setlocal(true);
447                                                 
448                                                 $$ = query;
449                                         }
450                                 ;
451
452 decl_cursor_args :
453                                         {
454                                                 $$ = NULL;
455                                         }
456                                 | '(' decl_cursor_arglist ')'
457                                         {
458                                                 /* Copy the temp arrays to malloc'd storage */
459                                                 int nfields = $2->nfields;
460                                                 char **ftmp;
461                                                 int *vtmp;
462
463                                                 ftmp = malloc(nfields * sizeof(char *));
464                                                 vtmp = malloc(nfields * sizeof(int));
465                                                 memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *));
466                                                 memcpy(vtmp, $2->varnos, nfields * sizeof(int));
467
468                                                 pfree((char *)($2->fieldnames));
469                                                 pfree((char *)($2->varnos));
470
471                                                 $2->fieldnames = ftmp;
472                                                 $2->varnos = vtmp;
473
474                                                 plpgsql_adddatum((PLpgSQL_datum *)$2);
475
476                                                 $$ = $2;
477                                         }
478                                 ;
479
480 decl_cursor_arglist : decl_cursor_arg
481                                         {
482                                                 PLpgSQL_row *new;
483
484                                                 new = malloc(sizeof(PLpgSQL_row));
485                                                 memset(new, 0, sizeof(PLpgSQL_row));
486
487                                                 new->dtype = PLPGSQL_DTYPE_ROW;
488                                                 new->refname = strdup("*internal*");
489                                                 new->lineno = yylineno;
490                                                 new->rowtypeclass = InvalidOid;
491                                                 /*
492                                                  * We make temporary fieldnames/varnos arrays that
493                                                  * are much bigger than necessary.  We will resize
494                                                  * them to just the needed size in the
495                                                  * decl_cursor_args production.
496                                                  */
497                                                 new->fieldnames = palloc(1024 * sizeof(char *));
498                                                 new->varnos = palloc(1024 * sizeof(int));
499                                                 new->nfields = 1;
500
501                                                 new->fieldnames[0] = $1->refname;
502                                                 new->varnos[0] = $1->varno;
503
504                                                 $$ = new;
505                                         }
506                                 | decl_cursor_arglist ',' decl_cursor_arg
507                                         {
508                                                 int i = $1->nfields++;
509
510                                                 $1->fieldnames[i] = $3->refname;
511                                                 $1->varnos[i] = $3->varno;
512
513                                                 $$ = $1;
514                                         }
515                                 ;
516
517 decl_cursor_arg : decl_varname decl_datatype
518                                         {
519                                                 PLpgSQL_var *new;
520
521                                                 new = malloc(sizeof(PLpgSQL_var));
522                                                 memset(new, 0, sizeof(PLpgSQL_var));
523
524                                                 new->dtype              = PLPGSQL_DTYPE_VAR;
525                                                 new->refname    = $1.name;
526                                                 new->lineno             = $1.lineno;
527
528                                                 new->datatype   = $2;
529                                                 new->isconst    = false;
530                                                 new->notnull    = false;
531
532                                                 plpgsql_adddatum((PLpgSQL_datum *)new);
533                                                 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
534                                                                                    $1.name);
535                                                 
536                                                 $$ = new;
537                                         }
538                                 ;
539
540 decl_is_from    :       K_IS |          /* Oracle */
541                                         K_FOR;          /* ANSI */
542
543 decl_aliasitem  : T_WORD
544                                         {
545                                                 char    *name;
546                                                 PLpgSQL_nsitem *nsi;
547
548                                                 plpgsql_convert_ident(yytext, &name, 1);
549                                                 if (name[0] != '$')
550                                                         yyerror("can only alias positional parameters");
551
552                                                 plpgsql_ns_setlocal(false);
553                                                 nsi = plpgsql_ns_lookup(name, NULL);
554                                                 if (nsi == NULL)
555                                                 {
556                                                         plpgsql_error_lineno = yylineno;
557                                                         elog(ERROR, "function has no parameter %s", name);
558                                                 }
559
560                                                 plpgsql_ns_setlocal(true);
561
562                                                 pfree(name);
563
564                                                 $$ = nsi;
565                                         }
566                                 ;
567
568 decl_rowtype    : T_ROW
569                                         {
570                                                 $$ = yylval.row;
571                                         }
572                                 ;
573
574 decl_varname    : T_WORD
575                                         {
576                                                 char    *name;
577
578                                                 plpgsql_convert_ident(yytext, &name, 1);
579                                                 /* name should be malloc'd for use as varname */
580                                                 $$.name = strdup(name);
581                                                 $$.lineno  = yylineno;
582                                                 pfree(name);
583                                         }
584                                 ;
585
586 decl_renname    : T_WORD
587                                         {
588                                                 char    *name;
589
590                                                 plpgsql_convert_ident(yytext, &name, 1);
591                                                 /* the result must be palloc'd, see plpgsql_ns_rename */
592                                                 $$ = name;
593                                         }
594                                 ;
595
596 decl_const              :
597                                         { $$ = 0; }
598                                 | K_CONSTANT
599                                         { $$ = 1; }
600                                 ;
601
602 decl_datatype   :
603                                         {
604                                                 /*
605                                                  * If there's a lookahead token, read_datatype
606                                                  * should consume it.
607                                                  */
608                                                 $$ = read_datatype(yychar);
609                                                 yyclearin;
610                                         }
611                                 ;
612
613 decl_notnull    :
614                                         { $$ = 0; }
615                                 | K_NOT K_NULL
616                                         { $$ = 1; }
617                                 ;
618
619 decl_defval             : ';'
620                                         { $$ = NULL; }
621                                 | decl_defkey
622                                         {
623                                                 int                             tok;
624                                                 int                             lno;
625                                                 PLpgSQL_dstring ds;
626                                                 PLpgSQL_expr    *expr;
627
628                                                 lno = yylineno;
629                                                 expr = malloc(sizeof(PLpgSQL_expr));
630                                                 plpgsql_dstring_init(&ds);
631                                                 plpgsql_dstring_append(&ds, "SELECT ");
632
633                                                 expr->dtype   = PLPGSQL_DTYPE_EXPR;
634                                                 expr->plan        = NULL;
635                                                 expr->nparams = 0;
636
637                                                 tok = yylex();
638                                                 switch (tok)
639                                                 {
640                                                         case 0:
641                                                                 yyerror("unexpected end of file");
642                                                         case K_NULL:
643                                                                 if (yylex() != ';')
644                                                                         yyerror("expected ; after NULL");
645
646                                                                 free(expr);
647                                                                 plpgsql_dstring_free(&ds);
648
649                                                                 $$ = NULL;
650                                                                 break;
651
652                                                         default:
653                                                                 plpgsql_dstring_append(&ds, yytext);
654                                                                 while ((tok = yylex()) != ';')
655                                                                 {
656                                                                         if (tok == 0)
657                                                                                 yyerror("unterminated default value");
658
659                                                                         if (plpgsql_SpaceScanned)
660                                                                                 plpgsql_dstring_append(&ds, " ");
661                                                                         plpgsql_dstring_append(&ds, yytext);
662                                                                 }
663                                                                 expr->query = strdup(plpgsql_dstring_get(&ds));
664                                                                 plpgsql_dstring_free(&ds);
665
666                                                                 $$ = expr;
667                                                                 break;
668                                                 }
669                                         }
670                                 ;
671
672 decl_defkey             : K_ASSIGN
673                                 | K_DEFAULT
674                                 ;
675
676 proc_sect               :
677                                         {
678                                                         PLpgSQL_stmts   *new;
679
680                                                         new = malloc(sizeof(PLpgSQL_stmts));
681                                                         memset(new, 0, sizeof(PLpgSQL_stmts));
682                                                         $$ = new;
683                                         }
684                                 | proc_stmts
685                                         { $$ = $1; }
686                                 ;
687
688 proc_stmts              : proc_stmts proc_stmt
689                                                 {
690                                                                 if ($1->stmts_used == $1->stmts_alloc)
691                                                                 {
692                                                                         $1->stmts_alloc *= 2;
693                                                                         $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
694                                                                 }
695                                                                 $1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
696
697                                                                 $$ = $1;
698                                                 }
699                                 | proc_stmt
700                                                 {
701                                                                 PLpgSQL_stmts   *new;
702
703                                                                 new = malloc(sizeof(PLpgSQL_stmts));
704                                                                 memset(new, 0, sizeof(PLpgSQL_stmts));
705
706                                                                 new->stmts_alloc = 64;
707                                                                 new->stmts_used  = 1;
708                                                                 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
709                                                                 new->stmts[0] = (struct PLpgSQL_stmt *)$1;
710
711                                                                 $$ = new;
712
713                                                 }
714                                 ;
715
716 proc_stmt               : pl_block ';'
717                                                 { $$ = $1; }
718                                 | stmt_assign
719                                                 { $$ = $1; }
720                                 | stmt_if
721                                                 { $$ = $1; }
722                                 | stmt_loop
723                                                 { $$ = $1; }
724                                 | stmt_while
725                                                 { $$ = $1; }
726                                 | stmt_fori
727                                                 { $$ = $1; }
728                                 | stmt_fors
729                                                 { $$ = $1; }
730                                 | stmt_select
731                                                 { $$ = $1; }
732                                 | stmt_exit
733                                                 { $$ = $1; }
734                                 | stmt_return
735                                                 { $$ = $1; }
736                                 | stmt_return_next
737                                                 { $$ = $1; }
738                                 | stmt_raise
739                                                 { $$ = $1; }
740                                 | stmt_execsql
741                                                 { $$ = $1; }
742                                 | stmt_dynexecute
743                                                 { $$ = $1; }
744                                 | stmt_dynfors
745                                                 { $$ = $1; }
746                                 | stmt_perform
747                                                 { $$ = $1; }
748                                 | stmt_getdiag
749                                                 { $$ = $1; }
750                                 | stmt_open
751                                                 { $$ = $1; }
752                                 | stmt_fetch
753                                                 { $$ = $1; }
754                                 | stmt_close
755                                                 { $$ = $1; }
756                                 ;
757
758 stmt_perform    : K_PERFORM lno expr_until_semi
759                                         {
760                                                 PLpgSQL_stmt_perform *new;
761
762                                                 new = malloc(sizeof(PLpgSQL_stmt_perform));
763                                                 memset(new, 0, sizeof(PLpgSQL_stmt_perform));
764
765                                                 new->cmd_type = PLPGSQL_STMT_PERFORM;
766                                                 new->lineno   = $2;
767                                                 new->expr  = $3;
768
769                                                 $$ = (PLpgSQL_stmt *)new;
770                                         }
771                                 ;
772
773 stmt_assign             : assign_var lno K_ASSIGN expr_until_semi
774                                         {
775                                                 PLpgSQL_stmt_assign *new;
776
777                                                 new = malloc(sizeof(PLpgSQL_stmt_assign));
778                                                 memset(new, 0, sizeof(PLpgSQL_stmt_assign));
779
780                                                 new->cmd_type = PLPGSQL_STMT_ASSIGN;
781                                                 new->lineno   = $2;
782                                                 new->varno = $1;
783                                                 new->expr  = $4;
784
785                                                 $$ = (PLpgSQL_stmt *)new;
786                                         }
787                                 ;
788
789 stmt_getdiag    : K_GET K_DIAGNOSTICS lno getdiag_list ';'
790                                         {
791                                                 PLpgSQL_stmt_getdiag     *new;
792
793                                                 new = malloc(sizeof(PLpgSQL_stmt_getdiag));
794                                                 memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
795
796                                                 new->cmd_type = PLPGSQL_STMT_GETDIAG;
797                                                 new->lineno   = $3;
798                                                 new->ndtitems = $4.nused;
799                                                 new->dtitems  = malloc(sizeof(PLpgSQL_diag_item) * $4.nused);
800                                                 memcpy(new->dtitems, $4.dtitems, sizeof(PLpgSQL_diag_item) * $4.nused);
801
802                                                 $$ = (PLpgSQL_stmt *)new;
803                                         }
804                                 ;
805
806 getdiag_list : getdiag_list ',' getdiag_target K_ASSIGN getdiag_item
807                                         {
808                                                 if ($1.nused == $1.nalloc)
809                                                 {
810                                                         $1.nalloc *= 2;
811                                                         $1.dtitems = repalloc($1.dtitems, sizeof(PLpgSQL_diag_item) * $1.nalloc);
812                                                 }
813                                                 $1.dtitems[$1.nused].target = $3;
814                                                 $1.dtitems[$1.nused].item   = $5;
815                                                 $1.nused++;
816
817                                                 $$.nalloc = $1.nalloc;
818                                                 $$.nused  = $1.nused;
819                                                 $$.dtitems = $1.dtitems;
820                                         }
821                                 | getdiag_target K_ASSIGN getdiag_item
822                                         {
823                                                 $$.nalloc = 1;
824                                                 $$.nused  = 1;
825                                                 $$.dtitems = palloc(sizeof(PLpgSQL_diag_item) * $$.nalloc);
826                                                 $$.dtitems[0].target = $1;
827                                                 $$.dtitems[0].item   = $3;
828                                         }
829                                 ;
830
831 getdiag_item : K_ROW_COUNT
832                                         {
833                                                 $$ = PLPGSQL_GETDIAG_ROW_COUNT;
834                                         }
835                                 | K_RESULT_OID
836                                         {
837                                                 $$ = PLPGSQL_GETDIAG_RESULT_OID;
838                                         }
839                                 ;
840
841 getdiag_target  : T_VARIABLE
842                                         {
843                                                 check_assignable(yylval.variable);
844                                                 $$ = yylval.variable->dno;
845                                         }
846                                 ;
847
848
849 assign_var              : T_VARIABLE
850                                         {
851                                                 check_assignable(yylval.variable);
852                                                 $$ = yylval.variable->dno;
853                                         }
854                                 | assign_var '[' expr_until_rightbracket
855                                         {
856                                                 PLpgSQL_arrayelem       *new;
857
858                                                 new = malloc(sizeof(PLpgSQL_arrayelem));
859                                                 memset(new, 0, sizeof(PLpgSQL_arrayelem));
860
861                                                 new->dtype              = PLPGSQL_DTYPE_ARRAYELEM;
862                                                 new->subscript  = $3;
863                                                 new->arrayparentno = $1;
864
865                                                 plpgsql_adddatum((PLpgSQL_datum *)new);
866
867                                                 $$ = new->dno;
868                                         }
869                                 ;
870
871 stmt_if                 : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
872                                         {
873                                                 PLpgSQL_stmt_if *new;
874
875                                                 new = malloc(sizeof(PLpgSQL_stmt_if));
876                                                 memset(new, 0, sizeof(PLpgSQL_stmt_if));
877
878                                                 new->cmd_type   = PLPGSQL_STMT_IF;
879                                                 new->lineno             = $2;
880                                                 new->cond               = $3;
881                                                 new->true_body  = $4;
882                                                 new->false_body = $5;
883
884                                                 $$ = (PLpgSQL_stmt *)new;
885                                         }
886                                 ;
887
888 stmt_else               :
889                                         {
890                                                         PLpgSQL_stmts   *new;
891
892                                                         new = malloc(sizeof(PLpgSQL_stmts));
893                                                         memset(new, 0, sizeof(PLpgSQL_stmts));
894                                                         $$ = new;
895                                         }
896                                 | K_ELSIF lno expr_until_then proc_sect stmt_else
897                                         {
898                                           /*
899                                            * Translate the structure:      into:
900                                            *
901                                            * IF c1 THEN                                    IF c1 THEN            
902                                            *     ...                                               ...                           
903                                            * ELSIF c2 THEN                                 ELSE 
904                                            *                                                               IF c2 THEN   
905                                            *     ...                                                       ...                           
906                                            * ELSE                                                          ELSE                          
907                                            *     ...                                                       ...                           
908                                            * END IF                                                        END IF                        
909                                            *                                                       END IF
910                                            * 
911                                            */
912
913                                                 PLpgSQL_stmts   *new;
914                                                 PLpgSQL_stmt_if *new_if;
915
916                                                 /* first create a new if-statement */
917                                                 new_if = malloc(sizeof(PLpgSQL_stmt_if));
918                                                 memset(new_if, 0, sizeof(PLpgSQL_stmt_if));
919
920                                                 new_if->cmd_type        = PLPGSQL_STMT_IF;
921                                                 new_if->lineno          = $2;
922                                                 new_if->cond            = $3;
923                                                 new_if->true_body       = $4;
924                                                 new_if->false_body      = $5;
925                                                 
926                                                 /* this is a 'container' for the if-statement */
927                                                 new = malloc(sizeof(PLpgSQL_stmts));
928                                                 memset(new, 0, sizeof(PLpgSQL_stmts));
929                                                 
930                                                 new->stmts_alloc = 64;
931                                                 new->stmts_used  = 1;
932                                                 new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
933                                                 new->stmts[0] = (struct PLpgSQL_stmt *)new_if;
934
935                                                 $$ = new;
936                                                 
937                                         }
938
939                                 | K_ELSE proc_sect
940                                         {
941                                                 $$ = $2;                                
942                                         }
943                                 ;
944
945 stmt_loop               : opt_label K_LOOP lno loop_body
946                                         {
947                                                 PLpgSQL_stmt_loop *new;
948
949                                                 new = malloc(sizeof(PLpgSQL_stmt_loop));
950                                                 memset(new, 0, sizeof(PLpgSQL_stmt_loop));
951
952                                                 new->cmd_type = PLPGSQL_STMT_LOOP;
953                                                 new->lineno   = $3;
954                                                 new->label        = $1;
955                                                 new->body         = $4;
956
957                                                 plpgsql_ns_pop();
958
959                                                 $$ = (PLpgSQL_stmt *)new;
960                                         }
961                                 ;
962
963 stmt_while              : opt_label K_WHILE lno expr_until_loop loop_body
964                                         {
965                                                 PLpgSQL_stmt_while *new;
966
967                                                 new = malloc(sizeof(PLpgSQL_stmt_while));
968                                                 memset(new, 0, sizeof(PLpgSQL_stmt_while));
969
970                                                 new->cmd_type = PLPGSQL_STMT_WHILE;
971                                                 new->lineno   = $3;
972                                                 new->label        = $1;
973                                                 new->cond         = $4;
974                                                 new->body         = $5;
975
976                                                 plpgsql_ns_pop();
977
978                                                 $$ = (PLpgSQL_stmt *)new;
979                                         }
980                                 ;
981
982 stmt_fori               : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
983                                         {
984                                                 PLpgSQL_stmt_fori               *new;
985
986                                                 new = malloc(sizeof(PLpgSQL_stmt_fori));
987                                                 memset(new, 0, sizeof(PLpgSQL_stmt_fori));
988
989                                                 new->cmd_type = PLPGSQL_STMT_FORI;
990                                                 new->lineno   = $3;
991                                                 new->label        = $1;
992                                                 new->var          = $4;
993                                                 new->reverse  = $6.reverse;
994                                                 new->lower        = $6.expr;
995                                                 new->upper        = $7;
996                                                 new->body         = $8;
997
998                                                 plpgsql_ns_pop();
999
1000                                                 $$ = (PLpgSQL_stmt *)new;
1001                                         }
1002                                 ;
1003
1004 fori_var                : fori_varname
1005                                         {
1006                                                 PLpgSQL_var             *new;
1007
1008                                                 new = malloc(sizeof(PLpgSQL_var));
1009                                                 memset(new, 0, sizeof(PLpgSQL_var));
1010
1011                                                 new->dtype              = PLPGSQL_DTYPE_VAR;
1012                                                 new->refname    = $1.name;
1013                                                 new->lineno             = $1.lineno;
1014
1015                                                 new->datatype   = plpgsql_parse_datatype("integer");
1016                                                 new->isconst    = false;
1017                                                 new->notnull    = false;
1018                                                 new->default_val = NULL;
1019
1020                                                 plpgsql_adddatum((PLpgSQL_datum *)new);
1021                                                 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
1022                                                                                                 $1.name);
1023
1024                                                 plpgsql_add_initdatums(NULL);
1025
1026                                                 $$ = new;
1027                                         }
1028                                 ;
1029
1030 fori_varname    : T_VARIABLE
1031                                         {
1032                                                 char    *name;
1033
1034                                                 plpgsql_convert_ident(yytext, &name, 1);
1035                                                 /* name should be malloc'd for use as varname */
1036                                                 $$.name = strdup(name);
1037                                                 $$.lineno  = yylineno;
1038                                                 pfree(name);
1039                                         }
1040                                 | T_WORD
1041                                         {
1042                                                 char    *name;
1043
1044                                                 plpgsql_convert_ident(yytext, &name, 1);
1045                                                 /* name should be malloc'd for use as varname */
1046                                                 $$.name = strdup(name);
1047                                                 $$.lineno  = yylineno;
1048                                                 pfree(name);
1049                                         }
1050                                 ;
1051
1052 fori_lower              :
1053                                         {
1054                                                 int                     tok;
1055
1056                                                 tok = yylex();
1057                                                 if (tok == K_REVERSE)
1058                                                 {
1059                                                         $$.reverse = 1;
1060                                                 }
1061                                                 else
1062                                                 {
1063                                                         $$.reverse = 0;
1064                                                         plpgsql_push_back_token(tok);
1065                                                 }
1066
1067                                                 $$.expr = plpgsql_read_expression(K_DOTDOT, "..");
1068                                         }
1069                                 ;
1070
1071 stmt_fors               : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
1072                                         {
1073                                                 PLpgSQL_stmt_fors               *new;
1074
1075                                                 new = malloc(sizeof(PLpgSQL_stmt_fors));
1076                                                 memset(new, 0, sizeof(PLpgSQL_stmt_fors));
1077
1078                                                 new->cmd_type = PLPGSQL_STMT_FORS;
1079                                                 new->lineno   = $3;
1080                                                 new->label        = $1;
1081                                                 switch ($4->dtype)
1082                                                 {
1083                                                         case PLPGSQL_DTYPE_REC:
1084                                                                 new->rec = $4;
1085                                                                 break;
1086                                                         case PLPGSQL_DTYPE_ROW:
1087                                                                 new->row = (PLpgSQL_row *)$4;
1088                                                                 break;
1089                                                         default:
1090                                                                 elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
1091                                                 }
1092                                                 new->query = $7;
1093                                                 new->body  = $8;
1094
1095                                                 plpgsql_ns_pop();
1096
1097                                                 $$ = (PLpgSQL_stmt *)new;
1098                                         }
1099                                 ;
1100
1101 stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body
1102                                         {
1103                                                 PLpgSQL_stmt_dynfors    *new;
1104
1105                                                 new = malloc(sizeof(PLpgSQL_stmt_dynfors));
1106                                                 memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
1107
1108                                                 new->cmd_type = PLPGSQL_STMT_DYNFORS;
1109                                                 new->lineno   = $3;
1110                                                 new->label        = $1;
1111                                                 switch ($4->dtype)
1112                                                 {
1113                                                         case PLPGSQL_DTYPE_REC:
1114                                                                 new->rec = $4;
1115                                                                 break;
1116                                                         case PLPGSQL_DTYPE_ROW:
1117                                                                 new->row = (PLpgSQL_row *)$4;
1118                                                                 break;
1119                                                         default:
1120                                                                 elog(ERROR, "unknown dtype %d in stmt_dynfors", $4->dtype);
1121                                                 }
1122                                                 new->query = $7;
1123                                                 new->body  = $8;
1124
1125                                                 plpgsql_ns_pop();
1126
1127                                                 $$ = (PLpgSQL_stmt *)new;
1128                                         }
1129                                 ;
1130
1131 fors_target             : T_RECORD
1132                                         { $$ = yylval.rec; }
1133                                 | T_ROW
1134                                         {
1135                                                 $$ = (PLpgSQL_rec *)(yylval.row);
1136                                         }
1137                                 ;
1138
1139 stmt_select             : K_SELECT lno
1140                                         {
1141                                                 $$ = make_select_stmt();
1142                                                 $$->lineno = $2;
1143                                         }
1144                                 ;
1145
1146 stmt_exit               : K_EXIT lno opt_exitlabel opt_exitcond
1147                                         {
1148                                                 PLpgSQL_stmt_exit *new;
1149
1150                                                 new = malloc(sizeof(PLpgSQL_stmt_exit));
1151                                                 memset(new, 0, sizeof(PLpgSQL_stmt_exit));
1152
1153                                                 new->cmd_type = PLPGSQL_STMT_EXIT;
1154                                                 new->lineno   = $2;
1155                                                 new->label        = $3;
1156                                                 new->cond         = $4;
1157
1158                                                 $$ = (PLpgSQL_stmt *)new;
1159                                         }
1160                                 ;
1161
1162 stmt_return             : K_RETURN lno
1163                                         {
1164                                                 PLpgSQL_stmt_return *new;
1165
1166                                                 new = malloc(sizeof(PLpgSQL_stmt_return));
1167                                                 memset(new, 0, sizeof(PLpgSQL_stmt_return));
1168
1169                                                 if (plpgsql_curr_compile->fn_retistuple &&
1170                                                         !plpgsql_curr_compile->fn_retset)
1171                                                 {
1172                                                         new->retrecno   = -1;
1173                                                         switch (yylex())
1174                                                         {
1175                                                                 case K_NULL:
1176                                                                         new->expr = NULL;
1177                                                                         break;
1178
1179                                                                 case T_ROW:
1180                                                                         new->expr = make_tupret_expr(yylval.row);
1181                                                                         break;
1182
1183                                                                 case T_RECORD:
1184                                                                         new->retrecno = yylval.rec->recno;
1185                                                                         new->expr = NULL;
1186                                                                         break;
1187
1188                                                                 default:
1189                                                                         yyerror("return type mismatch in function returning tuple");
1190                                                                         break;
1191                                                         }
1192                                                         if (yylex() != ';')
1193                                                                 yyerror("expected ';'");
1194                                                 }
1195                                                 else
1196                                                         new->expr = plpgsql_read_expression(';', ";");
1197
1198                                                 new->cmd_type = PLPGSQL_STMT_RETURN;
1199                                                 new->lineno   = $2;
1200
1201                                                 $$ = (PLpgSQL_stmt *)new;
1202                                         }
1203                                 ;
1204
1205 stmt_return_next: K_RETURN_NEXT lno
1206                                         {
1207                                                 PLpgSQL_stmt_return_next *new;
1208
1209                                                 new = malloc(sizeof(PLpgSQL_stmt_return_next));
1210                                                 memset(new, 0, sizeof(PLpgSQL_stmt_return_next));
1211
1212                                                 new->cmd_type   = PLPGSQL_STMT_RETURN_NEXT;
1213                                                 new->lineno             = $2;
1214
1215                                                 if (plpgsql_curr_compile->fn_retistuple)
1216                                                 {
1217                                                         int tok = yylex();
1218
1219                                                         if (tok == T_RECORD)
1220                                                                 new->rec = yylval.rec;
1221                                                         else if (tok == T_ROW)
1222                                                                 new->row = yylval.row;
1223                                                         else
1224                                                                 yyerror("Incorrect argument to RETURN NEXT");
1225
1226                                                         if (yylex() != ';')
1227                                                                 yyerror("Expected ';'");
1228                                                 }
1229                                                 else
1230                                                         new->expr = plpgsql_read_expression(';', ";");
1231
1232                                                 $$ = (PLpgSQL_stmt *)new;
1233                                         }
1234                                 ;
1235
1236 stmt_raise              : K_RAISE lno raise_level raise_msg raise_params ';'
1237                                         {
1238                                                 PLpgSQL_stmt_raise              *new;
1239
1240                                                 new = malloc(sizeof(PLpgSQL_stmt_raise));
1241
1242                                                 new->cmd_type   = PLPGSQL_STMT_RAISE;
1243                                                 new->lineno             = $2;
1244                                                 new->elog_level = $3;
1245                                                 new->message    = $4;
1246                                                 new->nparams    = $5.nused;
1247                                                 new->params             = malloc(sizeof(int) * $5.nused);
1248                                                 memcpy(new->params, $5.nums, sizeof(int) * $5.nused);
1249
1250                                                 $$ = (PLpgSQL_stmt *)new;
1251                                         }
1252                                 | K_RAISE lno raise_level raise_msg ';'
1253                                         {
1254                                                 PLpgSQL_stmt_raise              *new;
1255
1256                                                 new = malloc(sizeof(PLpgSQL_stmt_raise));
1257
1258                                                 new->cmd_type   = PLPGSQL_STMT_RAISE;
1259                                                 new->lineno             = $2;
1260                                                 new->elog_level = $3;
1261                                                 new->message    = $4;
1262                                                 new->nparams    = 0;
1263                                                 new->params             = NULL;
1264
1265                                                 $$ = (PLpgSQL_stmt *)new;
1266                                         }
1267                                 ;
1268
1269 raise_msg               : T_STRING
1270                                         {
1271                                                 $$ = strdup(yytext);
1272                                         }
1273                                 ;
1274
1275 raise_level             : K_EXCEPTION
1276                                         {
1277                                                 $$ = ERROR;
1278                                         }
1279                                 | K_WARNING
1280                                         {
1281                                                 $$ = WARNING;
1282                                         }
1283                                 | K_NOTICE
1284                                         {
1285                                                 $$ = NOTICE;
1286                                         }
1287                                 | K_INFO
1288                                         {
1289                                                 $$ = INFO;
1290                                         }
1291                                 | K_LOG
1292                                         {
1293                                                 $$ = LOG;
1294                                         }
1295                                 | K_DEBUG
1296                                         {
1297                                                 $$ = DEBUG1;
1298                                         }
1299                                 ;
1300
1301 raise_params    : raise_params raise_param
1302                                         {
1303                                                 if ($1.nused == $1.nalloc)
1304                                                 {
1305                                                         $1.nalloc *= 2;
1306                                                         $1.nums = repalloc($1.nums, sizeof(int) * $1.nalloc);
1307                                                 }
1308                                                 $1.nums[$1.nused++] = $2;
1309
1310                                                 $$.nalloc = $1.nalloc;
1311                                                 $$.nused  = $1.nused;
1312                                                 $$.nums   = $1.nums;
1313                                         }
1314                                 | raise_param
1315                                         {
1316                                                 $$.nalloc = 1;
1317                                                 $$.nused  = 1;
1318                                                 $$.nums   = palloc(sizeof(int) * $$.nalloc);
1319                                                 $$.nums[0] = $1;
1320                                         }
1321                                 ;
1322
1323 raise_param             : ',' T_VARIABLE
1324                                         {
1325                                                 $$ = yylval.variable->dno;
1326                                         }
1327                                 ;
1328
1329 loop_body               : proc_sect K_END K_LOOP ';'
1330                                         { $$ = $1; }
1331                                 ;
1332
1333 stmt_execsql    : execsql_start lno
1334                                         {
1335                                                 PLpgSQL_stmt_execsql    *new;
1336
1337                                                 new = malloc(sizeof(PLpgSQL_stmt_execsql));
1338                                                 new->cmd_type = PLPGSQL_STMT_EXECSQL;
1339                                                 new->lineno   = $2;
1340                                                 new->sqlstmt  = read_sql_stmt($1);
1341
1342                                                 $$ = (PLpgSQL_stmt *)new;
1343                                         }
1344                                 ;
1345
1346 stmt_dynexecute : K_EXECUTE lno expr_until_semi
1347                                                 {
1348                                                         PLpgSQL_stmt_dynexecute *new;
1349
1350                                                         new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
1351                                                         new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1352                                                         new->lineno   = $2;
1353                                                         new->query        = $3;
1354
1355                                                         $$ = (PLpgSQL_stmt *)new;
1356                                                 }
1357                                 ;
1358
1359 stmt_open               : K_OPEN lno cursor_varptr
1360                                         {
1361                                                 PLpgSQL_stmt_open *new;
1362                                                 int                               tok;
1363
1364                                                 new = malloc(sizeof(PLpgSQL_stmt_open));
1365                                                 memset(new, 0, sizeof(PLpgSQL_stmt_open));
1366
1367                                                 new->cmd_type = PLPGSQL_STMT_OPEN;
1368                                                 new->lineno = $2;
1369                                                 new->curvar = $3->varno;
1370
1371                                                 if ($3->cursor_explicit_expr == NULL)
1372                                                 {
1373                                                     tok = yylex();
1374
1375                                                         if (tok != K_FOR)
1376                                                         {
1377                                                                 plpgsql_error_lineno = $2;
1378                                                                 elog(ERROR, "syntax error at \"%s\" - expected FOR to open a reference cursor", yytext);
1379                                                         }
1380
1381                                                         tok = yylex();
1382                                                         switch (tok)
1383                                                         {
1384                                                                 case K_SELECT:
1385                                                                         new->query = read_sql_stmt("SELECT ");
1386                                                                         break;
1387
1388                                                                 case K_EXECUTE:
1389                                                                         new->dynquery = read_sql_stmt("SELECT ");
1390                                                                         break;
1391
1392                                                                 default:
1393                                                                         plpgsql_error_lineno = $2;
1394                                                                         elog(ERROR, "syntax error at \"%s\"", yytext);
1395                                                         }
1396
1397                                                 }
1398                                                 else
1399                                                 {
1400                                                         if ($3->cursor_explicit_argrow >= 0)
1401                                                         {
1402                                                                 char   *cp;
1403
1404                                                                 tok = yylex();
1405
1406                                                                 if (tok != '(')
1407                                                                 {
1408                                                                         plpgsql_error_lineno = yylineno;
1409                                                                         elog(ERROR, "cursor %s has arguments",
1410                                                                                  $3->refname);
1411                                                                 }
1412
1413                                                                 /*
1414                                                                  * Push back the '(', else read_sql_stmt
1415                                                                  * will complain about unbalanced parens.
1416                                                                  */
1417                                                                 plpgsql_push_back_token(tok);
1418
1419                                                                 new->argquery = read_sql_stmt("SELECT ");
1420
1421                                                                 /*
1422                                                                  * Now remove the leading and trailing parens,
1423                                                                  * because we want "select 1, 2", not
1424                                                                  * "select (1, 2)".
1425                                                                  */
1426                                                                 cp = new->argquery->query;
1427
1428                                                                 if (strncmp(cp, "SELECT", 6) != 0)
1429                                                                 {
1430                                                                         plpgsql_error_lineno = yylineno;
1431                                                                         elog(ERROR, "expected 'SELECT (', got '%s' (internal error)",
1432                                                                                  new->argquery->query);
1433                                                                 }
1434                                                                 cp += 6;
1435                                                                 while (*cp == ' ') /* could be more than 1 space here */
1436                                                                         cp++;
1437                                                                 if (*cp != '(')
1438                                                                 {
1439                                                                         plpgsql_error_lineno = yylineno;
1440                                                                         elog(ERROR, "expected 'SELECT (', got '%s' (internal error)",
1441                                                                                  new->argquery->query);
1442                                                                 }
1443                                                                 *cp = ' ';
1444
1445                                                                 cp += strlen(cp) - 1;
1446
1447                                                                 if (*cp != ')')
1448                                                                         yyerror("missing )");
1449                                                                 *cp = '\0';
1450                                                         }
1451                                                         else
1452                                                         {
1453                                                                 tok = yylex();
1454
1455                                                                 if (tok == '(')
1456                                                                 {
1457                                                                         plpgsql_error_lineno = yylineno;
1458                                                                         elog(ERROR, "cursor %s has no arguments", $3->refname);
1459                                                                 }
1460                                                                 
1461                                                                 if (tok != ';')
1462                                                                 {
1463                                                                         plpgsql_error_lineno = yylineno;
1464                                                                         elog(ERROR, "syntax error at \"%s\"", yytext);
1465                                                                 }
1466                                                         }
1467                                                 }
1468
1469                                                 $$ = (PLpgSQL_stmt *)new;
1470                                         }
1471                                 ;
1472
1473 stmt_fetch              : K_FETCH lno cursor_variable K_INTO
1474                                         {
1475                                                 PLpgSQL_stmt_fetch *new;
1476
1477                                                 new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1478                                                 new->curvar = $3;
1479
1480                                                 $$ = (PLpgSQL_stmt *)new;
1481                                                 $$->lineno = $2;
1482                                         }
1483                                 ;
1484
1485 stmt_close              : K_CLOSE lno cursor_variable ';'
1486                                         {
1487                                                 PLpgSQL_stmt_close *new;
1488
1489                                                 new = malloc(sizeof(PLpgSQL_stmt_close));
1490                                                 new->cmd_type = PLPGSQL_STMT_CLOSE;
1491                                                 new->lineno = $2;
1492                                                 new->curvar = $3;
1493
1494                                                 $$ = (PLpgSQL_stmt *)new;
1495                                         }
1496                                 ;
1497
1498 cursor_varptr   : T_VARIABLE
1499                                         {
1500                                                 if (yylval.variable->dtype != PLPGSQL_DTYPE_VAR)
1501                                                         yyerror("cursor variable must be a simple variable");
1502
1503                                                 if (((PLpgSQL_var *) yylval.variable)->datatype->typoid != REFCURSOROID)
1504                                                 {
1505                                                         plpgsql_error_lineno = yylineno;
1506                                                         elog(ERROR, "%s must be of type cursor or refcursor",
1507                                                                  ((PLpgSQL_var *) yylval.variable)->refname);
1508                                                 }
1509                                                 $$ = (PLpgSQL_var *) yylval.variable;
1510                                         }
1511                                 ;
1512
1513 cursor_variable : T_VARIABLE
1514                                         {
1515                                                 if (yylval.variable->dtype != PLPGSQL_DTYPE_VAR)
1516                                                         yyerror("cursor variable must be a simple variable");
1517
1518                                                 if (((PLpgSQL_var *) yylval.variable)->datatype->typoid != REFCURSOROID)
1519                                                 {
1520                                                         plpgsql_error_lineno = yylineno;
1521                                                         elog(ERROR, "%s must be of type refcursor",
1522                                                                  ((PLpgSQL_var *) yylval.variable)->refname);
1523                                                 }
1524                                                 $$ = yylval.variable->dno;
1525                                         }
1526                                 ;
1527
1528 execsql_start   : T_WORD
1529                                         { $$ = strdup(yytext); }
1530                                 | T_ERROR
1531                                         { $$ = strdup(yytext); }
1532                                 ;
1533
1534 expr_until_semi :
1535                                         { $$ = plpgsql_read_expression(';', ";"); }
1536                                 ;
1537
1538 expr_until_rightbracket :
1539                                         { $$ = plpgsql_read_expression(']', "]"); }
1540                                 ;
1541
1542 expr_until_then :
1543                                         { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1544                                 ;
1545
1546 expr_until_loop :
1547                                         { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1548                                 ;
1549
1550 opt_label               :
1551                                         {
1552                                                 plpgsql_ns_push(NULL);
1553                                                 $$ = NULL;
1554                                         }
1555                                 | '<' '<' opt_lblname '>' '>'
1556                                         {
1557                                                 plpgsql_ns_push($3);
1558                                                 $$ = $3;
1559                                         }
1560                                 ;
1561
1562 opt_exitlabel   :
1563                                         { $$ = NULL; }
1564                                 | T_LABEL
1565                                         { $$ = strdup(yytext); }
1566                                 ;
1567
1568 opt_exitcond    : ';'
1569                                         { $$ = NULL; }
1570                                 | K_WHEN expr_until_semi
1571                                         { $$ = $2; }
1572                                 ;
1573
1574 opt_lblname             : T_WORD
1575                                         {
1576                                                 char    *name;
1577
1578                                                 plpgsql_convert_ident(yytext, &name, 1);
1579                                                 $$ = strdup(name);
1580                                                 pfree(name);
1581                                         }
1582                                 ;
1583
1584 lno                             :
1585                                         {
1586                                                 plpgsql_error_lineno = yylineno;
1587                                                 $$ = yylineno;
1588                                         }
1589                                 ;
1590
1591 %%
1592
1593
1594 PLpgSQL_expr *
1595 plpgsql_read_expression(int until, const char *expected)
1596 {
1597         return read_sql_construct(until, expected, true, "SELECT ");
1598 }
1599
1600 static PLpgSQL_expr *
1601 read_sql_stmt(const char *sqlstart)
1602 {
1603         return read_sql_construct(';', ";", false, sqlstart);
1604 }
1605
1606 static PLpgSQL_expr *
1607 read_sql_construct(int until,
1608                                    const char *expected,
1609                                    bool isexpression,
1610                                    const char *sqlstart)
1611 {
1612         int                                     tok;
1613         int                                     lno;
1614         PLpgSQL_dstring         ds;
1615         int                                     parenlevel = 0;
1616         int                                     nparams = 0;
1617         int                                     params[1024];
1618         char                            buf[32];
1619         PLpgSQL_expr            *expr;
1620
1621         lno = yylineno;
1622         plpgsql_dstring_init(&ds);
1623         plpgsql_dstring_append(&ds, (char *) sqlstart);
1624
1625         for (;;)
1626         {
1627                 tok = yylex();
1628                 if (tok == until && parenlevel == 0)
1629                         break;
1630                 if (tok == '(' || tok == '[')
1631                         parenlevel++;
1632                 else if (tok == ')' || tok == ']')
1633                 {
1634                         parenlevel--;
1635                         if (parenlevel < 0)
1636                                 elog(ERROR, "mismatched parentheses");
1637                 }
1638                 /*
1639                  * End of function definition is an error, and we don't expect to
1640                  * hit a semicolon either (unless it's the until symbol, in which
1641                  * case we should have fallen out above).
1642                  */
1643                 if (tok == 0 || tok == ';')
1644                 {
1645                         plpgsql_error_lineno = lno;
1646                         if (parenlevel != 0)
1647                                 elog(ERROR, "mismatched parentheses");
1648                         if (isexpression)
1649                                 elog(ERROR, "missing %s at end of SQL expression",
1650                                          expected);
1651                         else
1652                                 elog(ERROR, "missing %s at end of SQL statement",
1653                                          expected);
1654                         break;
1655                 }
1656                 if (plpgsql_SpaceScanned)
1657                         plpgsql_dstring_append(&ds, " ");
1658                 switch (tok)
1659                 {
1660                         case T_VARIABLE:
1661                                 params[nparams] = yylval.variable->dno;
1662                                 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1663                                 plpgsql_dstring_append(&ds, buf);
1664                                 break;
1665
1666                         default:
1667                                 plpgsql_dstring_append(&ds, yytext);
1668                                 break;
1669                 }
1670         }
1671
1672         expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1673         expr->dtype                     = PLPGSQL_DTYPE_EXPR;
1674         expr->query                     = strdup(plpgsql_dstring_get(&ds));
1675         expr->plan                      = NULL;
1676         expr->nparams           = nparams;
1677         while(nparams-- > 0)
1678                 expr->params[nparams] = params[nparams];
1679         plpgsql_dstring_free(&ds);
1680
1681         return expr;
1682 }
1683
1684 static PLpgSQL_type *
1685 read_datatype(int tok)
1686 {
1687         int                                     lno;
1688         PLpgSQL_dstring         ds;
1689         PLpgSQL_type            *result;
1690         bool                            needspace = false;
1691         int                                     parenlevel = 0;
1692
1693         lno = yylineno;
1694
1695         /* Often there will be a lookahead token, but if not, get one */
1696         if (tok == YYEMPTY)
1697                 tok = yylex();
1698
1699         if (tok == T_DTYPE)
1700         {
1701                 /* lexer found word%TYPE and did its thing already */
1702                 return yylval.dtype;
1703         }
1704
1705         plpgsql_dstring_init(&ds);
1706
1707         while (tok != ';')
1708         {
1709                 if (tok == 0)
1710                 {
1711                         plpgsql_error_lineno = lno;
1712                         if (parenlevel != 0)
1713                                 elog(ERROR, "mismatched parentheses");
1714                         elog(ERROR, "incomplete datatype declaration");
1715                 }
1716                 /* Possible followers for datatype in a declaration */
1717                 if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
1718                         break;
1719                 /* Possible followers for datatype in a cursor_arg list */
1720                 if ((tok == ',' || tok == ')') && parenlevel == 0)
1721                         break;
1722                 if (tok == '(')
1723                         parenlevel++;
1724                 else if (tok == ')')
1725                         parenlevel--;
1726                 if (needspace)
1727                         plpgsql_dstring_append(&ds, " ");
1728                 needspace = true;
1729                 plpgsql_dstring_append(&ds, yytext);
1730
1731                 tok = yylex();
1732         }
1733
1734         plpgsql_push_back_token(tok);
1735
1736         plpgsql_error_lineno = lno;     /* in case of error in parse_datatype */
1737
1738         result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
1739
1740         plpgsql_dstring_free(&ds);
1741
1742         return result;
1743 }
1744
1745
1746 static PLpgSQL_stmt *
1747 make_select_stmt(void)
1748 {
1749         PLpgSQL_dstring         ds;
1750         int                                     nparams = 0;
1751         int                                     params[1024];
1752         char                            buf[32];
1753         PLpgSQL_expr            *expr;
1754         PLpgSQL_row                     *row = NULL;
1755         PLpgSQL_rec                     *rec = NULL;
1756         int                                     tok = 0;
1757         int                                     have_nexttok = 0;
1758         int                                     have_into = 0;
1759
1760         plpgsql_dstring_init(&ds);
1761         plpgsql_dstring_append(&ds, "SELECT ");
1762
1763         while(1)
1764         {
1765                 if (!have_nexttok)
1766                         tok = yylex();
1767                 have_nexttok = 0;
1768                 if (tok == ';')
1769                         break;
1770                 if (tok == 0)
1771                 {
1772                         plpgsql_error_lineno = yylineno;
1773                         elog(ERROR, "unexpected end of file");
1774                 }
1775                 if (tok == K_INTO)
1776                 {
1777                         if (have_into)
1778                         {
1779                                 plpgsql_error_lineno = yylineno;
1780                                 elog(ERROR, "INTO specified more than once");
1781                         }
1782                         tok = yylex();
1783                         switch (tok)
1784                         {
1785                                 case T_ROW:
1786                                         row = yylval.row;
1787                                         have_into = 1;
1788                                         break;
1789
1790                                 case T_RECORD:
1791                                         rec = yylval.rec;
1792                                         have_into = 1;
1793                                         break;
1794
1795                                 case T_VARIABLE:
1796                                 {
1797                                         int                             nfields = 1;
1798                                         char                    *fieldnames[1024];
1799                                         int                             varnos[1024];
1800
1801                                         check_assignable(yylval.variable);
1802                                         fieldnames[0] = strdup(yytext);
1803                                         varnos[0]         = yylval.variable->dno;
1804
1805                                         while ((tok = yylex()) == ',')
1806                                         {
1807                                                 tok = yylex();
1808                                                 switch(tok)
1809                                                 {
1810                                                         case T_VARIABLE:
1811                                                                 check_assignable(yylval.variable);
1812                                                                 fieldnames[nfields] = strdup(yytext);
1813                                                                 varnos[nfields++]       = yylval.variable->dno;
1814                                                                 break;
1815
1816                                                         default:
1817                                                                 plpgsql_error_lineno = yylineno;
1818                                                                 elog(ERROR, "plpgsql: %s is not a variable",
1819                                                                          yytext);
1820                                                 }
1821                                         }
1822                                         have_nexttok = 1;
1823
1824                                         row = malloc(sizeof(PLpgSQL_row));
1825                                         row->dtype = PLPGSQL_DTYPE_ROW;
1826                                         row->refname = strdup("*internal*");
1827                                         row->lineno = yylineno;
1828                                         row->rowtypeclass = InvalidOid;
1829                                         row->nfields = nfields;
1830                                         row->fieldnames = malloc(sizeof(char *) * nfields);
1831                                         row->varnos = malloc(sizeof(int) * nfields);
1832                                         while (--nfields >= 0)
1833                                         {
1834                                                 row->fieldnames[nfields] = fieldnames[nfields];
1835                                                 row->varnos[nfields] = varnos[nfields];
1836                                         }
1837
1838                                         plpgsql_adddatum((PLpgSQL_datum *)row);
1839
1840                                         have_into = 1;
1841                                 }
1842                                 break;
1843
1844                                 default:
1845                                         /* Treat the INTO as non-special */
1846                                         plpgsql_dstring_append(&ds, " INTO ");
1847                                         have_nexttok = 1;
1848                                         break;
1849                         }
1850                         continue;
1851                 }
1852
1853                 if (plpgsql_SpaceScanned)
1854                         plpgsql_dstring_append(&ds, " ");
1855                 switch (tok)
1856                 {
1857                         case T_VARIABLE:
1858                                 params[nparams] = yylval.variable->dno;
1859                                 snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1860                                 plpgsql_dstring_append(&ds, buf);
1861                                 break;
1862
1863                         default:
1864                                 plpgsql_dstring_append(&ds, yytext);
1865                                 break;
1866                 }
1867         }
1868
1869         expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1870         expr->dtype                     = PLPGSQL_DTYPE_EXPR;
1871         expr->query                     = strdup(plpgsql_dstring_get(&ds));
1872         expr->plan                      = NULL;
1873         expr->nparams           = nparams;
1874         while(nparams-- > 0)
1875                 expr->params[nparams] = params[nparams];
1876         plpgsql_dstring_free(&ds);
1877
1878         if (have_into)
1879         {
1880                 PLpgSQL_stmt_select *select;
1881
1882                 select = malloc(sizeof(PLpgSQL_stmt_select));
1883                 memset(select, 0, sizeof(PLpgSQL_stmt_select));
1884                 select->cmd_type = PLPGSQL_STMT_SELECT;
1885                 select->rec              = rec;
1886                 select->row              = row;
1887                 select->query    = expr;
1888
1889                 return (PLpgSQL_stmt *)select;
1890         }
1891         else
1892         {
1893                 PLpgSQL_stmt_execsql *execsql;
1894
1895                 execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
1896                 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
1897                 execsql->sqlstmt  = expr;
1898
1899                 return (PLpgSQL_stmt *)execsql;
1900         }
1901 }
1902
1903
1904 static PLpgSQL_stmt *
1905 make_fetch_stmt(void)
1906 {
1907         int                                     tok;
1908         PLpgSQL_row                *row = NULL;
1909         PLpgSQL_rec                *rec = NULL;
1910         PLpgSQL_stmt_fetch *fetch;
1911         int                                     have_nexttok = 0;
1912
1913         /* We have already parsed everything through the INTO keyword */
1914
1915         tok = yylex();
1916         switch (tok)
1917         {
1918                 case T_ROW:
1919                         row = yylval.row;
1920                         break;
1921
1922                 case T_RECORD:
1923                         rec = yylval.rec;
1924                         break;
1925
1926                 case T_VARIABLE:
1927                         {
1928                                 int                             nfields = 1;
1929                                 char                    *fieldnames[1024];
1930                                 int                             varnos[1024];
1931
1932                                 check_assignable(yylval.variable);
1933                                 fieldnames[0] = strdup(yytext);
1934                                 varnos[0]         = yylval.variable->dno;
1935
1936                                 while ((tok = yylex()) == ',')
1937                                 {
1938                                         tok = yylex();
1939                                         switch(tok)
1940                                         {
1941                                                 case T_VARIABLE:
1942                                                         check_assignable(yylval.variable);
1943                                                         fieldnames[nfields] = strdup(yytext);
1944                                                         varnos[nfields++]       = yylval.variable->dno;
1945                                                         break;
1946
1947                                                 default:
1948                                                         plpgsql_error_lineno = yylineno;
1949                                                         elog(ERROR, "plpgsql: %s is not a variable",
1950                                                                  yytext);
1951                                         }
1952                                 }
1953                                 have_nexttok = 1;
1954
1955                                 row = malloc(sizeof(PLpgSQL_row));
1956                                 row->dtype = PLPGSQL_DTYPE_ROW;
1957                                 row->refname = strdup("*internal*");
1958                                 row->lineno = yylineno;
1959                                 row->rowtypeclass = InvalidOid;
1960                                 row->nfields = nfields;
1961                                 row->fieldnames = malloc(sizeof(char *) * nfields);
1962                                 row->varnos = malloc(sizeof(int) * nfields);
1963                                 while (--nfields >= 0)
1964                                 {
1965                                         row->fieldnames[nfields] = fieldnames[nfields];
1966                                         row->varnos[nfields] = varnos[nfields];
1967                                 }
1968
1969                                 plpgsql_adddatum((PLpgSQL_datum *)row);
1970                         }
1971                         break;
1972
1973                 default:
1974                         yyerror("syntax error");
1975         }
1976
1977         if (!have_nexttok)
1978                 tok = yylex();
1979
1980         if (tok != ';')
1981                 yyerror("syntax error");
1982
1983         fetch = malloc(sizeof(PLpgSQL_stmt_select));
1984         memset(fetch, 0, sizeof(PLpgSQL_stmt_fetch));
1985         fetch->cmd_type = PLPGSQL_STMT_FETCH;
1986         fetch->rec               = rec;
1987         fetch->row               = row;
1988
1989         return (PLpgSQL_stmt *)fetch;
1990 }
1991
1992
1993 static PLpgSQL_expr *
1994 make_tupret_expr(PLpgSQL_row *row)
1995 {
1996         PLpgSQL_dstring         ds;
1997         PLpgSQL_expr            *expr;
1998         int                                     i;
1999         char                            buf[16];
2000
2001         expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
2002         expr->dtype                     = PLPGSQL_DTYPE_EXPR;
2003
2004         plpgsql_dstring_init(&ds);
2005         plpgsql_dstring_append(&ds, "SELECT ");
2006
2007         for (i = 0; i < row->nfields; i++)
2008         {
2009                 sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
2010                 plpgsql_dstring_append(&ds, buf);
2011                 expr->params[i] = row->varnos[i];
2012         }
2013
2014         expr->query                     = strdup(plpgsql_dstring_get(&ds));
2015         expr->plan                      = NULL;
2016         expr->plan_argtypes = NULL;
2017         expr->nparams           = row->nfields;
2018
2019         plpgsql_dstring_free(&ds);
2020         return expr;
2021 }
2022
2023 static void
2024 check_assignable(PLpgSQL_datum *datum)
2025 {
2026         switch (datum->dtype)
2027         {
2028                 case PLPGSQL_DTYPE_VAR:
2029                         if (((PLpgSQL_var *) datum)->isconst)
2030                         {
2031                                 plpgsql_error_lineno = yylineno;
2032                                 elog(ERROR, "%s is declared CONSTANT",
2033                                          ((PLpgSQL_var *) datum)->refname);
2034                         }
2035                         break;
2036                 case PLPGSQL_DTYPE_RECFIELD:
2037                         /* always assignable? */
2038                         break;
2039                 case PLPGSQL_DTYPE_ARRAYELEM:
2040                         /* always assignable? */
2041                         break;
2042                 case PLPGSQL_DTYPE_TRIGARG:
2043                         yyerror("cannot assign to tg_argv");
2044                         break;
2045                 default:
2046                         yyerror("check_assignable: unexpected datum type");
2047                         break;
2048         }
2049 }
2050
2051 #include "pl_scan.c"