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