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