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