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