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