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