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