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