~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/pl/plpgsql/src/gram.y

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

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