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