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