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