1 %{
2 /*-------------------------------------------------------------------------
3 *
4 * pl_gram.y - Parser for the PL/pgSQL procedural language
5 *
6 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/pl/plpgsql/src/pl_gram.y
12 *
13 *-------------------------------------------------------------------------
14 */
15
16 #include "postgres.h"
17
18 #include "catalog/namespace.h"
19 #include "catalog/pg_proc.h"
20 #include "catalog/pg_type.h"
21 #include "parser/parser.h"
22 #include "parser/parse_type.h"
23 #include "parser/scanner.h"
24 #include "parser/scansup.h"
25 #include "utils/builtins.h"
26
27 #include "plpgsql.h"
28
29
30 /* Location tracking support --- simpler than bison's default */
31 #define YYLLOC_DEFAULT(Current, Rhs, N) \
32 do { \
33 if (N) \
34 (Current) = (Rhs)[1]; \
35 else \
36 (Current) = (Rhs)[0]; \
37 } while (0)
38
39 /*
40 * Bison doesn't allocate anything that needs to live across parser calls,
41 * so we can easily have it use palloc instead of malloc. This prevents
42 * memory leaks if we error out during parsing. Note this only works with
43 * bison >= 2.0. However, in bison 1.875 the default is to use alloca()
44 * if possible, so there's not really much problem anyhow, at least if
45 * you're building with gcc.
46 */
47 #define YYMALLOC palloc
48 #define YYFREE pfree
49
50
51 typedef struct
52 {
53 int location;
54 } sql_error_callback_arg;
55
56 #define parser_errposition(pos) plpgsql_scanner_errposition(pos)
57
58 union YYSTYPE; /* need forward reference for tok_is_keyword */
59
60 static bool tok_is_keyword(int token, union YYSTYPE *lval,
61 int kw_token, const char *kw_str);
62 static void word_is_not_variable(PLword *word, int location);
63 static void cword_is_not_variable(PLcword *cword, int location);
64 static void current_token_is_not_variable(int tok);
65 static PLpgSQL_expr *read_sql_construct(int until,
66 int until2,
67 int until3,
68 const char *expected,
69 RawParseMode parsemode,
70 bool isexpression,
71 bool valid_sql,
72 bool trim,
73 int *startloc,
74 int *endtoken);
75 static PLpgSQL_expr *read_sql_expression(int until,
76 const char *expected);
77 static PLpgSQL_expr *read_sql_expression2(int until, int until2,
78 const char *expected,
79 int *endtoken);
80 static PLpgSQL_expr *read_sql_stmt(void);
81 static PLpgSQL_type *read_datatype(int tok);
82 static PLpgSQL_stmt *make_execsql_stmt(int firsttoken, int location);
83 static PLpgSQL_stmt_fetch *read_fetch_direction(void);
84 static void complete_direction(PLpgSQL_stmt_fetch *fetch,
85 bool *check_FROM);
86 static PLpgSQL_stmt *make_return_stmt(int location);
87 static PLpgSQL_stmt *make_return_next_stmt(int location);
88 static PLpgSQL_stmt *make_return_query_stmt(int location);
89 static PLpgSQL_stmt *make_case(int location, PLpgSQL_expr *t_expr,
90 List *case_when_list, List *else_stmts);
91 static char *NameOfDatum(PLwdatum *wdatum);
92 static void check_assignable(PLpgSQL_datum *datum, int location);
93 static void read_into_target(PLpgSQL_variable **target,
94 bool *strict);
95 static PLpgSQL_row *read_into_scalar_list(char *initial_name,
96 PLpgSQL_datum *initial_datum,
97 int initial_location);
98 static PLpgSQL_row *make_scalar_list1(char *initial_name,
99 PLpgSQL_datum *initial_datum,
100 int lineno, int location);
101 static void check_sql_expr(const char *stmt,
102 RawParseMode parseMode, int location);
103 static void plpgsql_sql_error_callback(void *arg);
104 static PLpgSQL_type *parse_datatype(const char *string, int location);
105 static void check_labels(const char *start_label,
106 const char *end_label,
107 int end_location);
108 static PLpgSQL_expr *read_cursor_args(PLpgSQL_var *cursor,
109 int until);
110 static List *read_raise_options(void);
111 static void check_raise_parameters(PLpgSQL_stmt_raise *stmt);
112
113 %}
114
115 %expect 0
116 %name-prefix="plpgsql_yy"
117 %locations
118
119 %union {
120 core_YYSTYPE core_yystype;
121 /* these fields must match core_YYSTYPE: */
122 int ival;
123 char *str;
124 const char *keyword;
125
126 PLword word;
127 PLcword cword;
128 PLwdatum wdatum;
129 bool boolean;
130 Oid oid;
131 struct
132 {
133 char *name;
134 int lineno;
135 } varname;
136 struct
137 {
138 char *name;
139 int lineno;
140 PLpgSQL_datum *scalar;
141 PLpgSQL_datum *row;
142 } forvariable;
143 struct
144 {
145 char *label;
146 int n_initvars;
147 int *initvarnos;
148 } declhdr;
149 struct
150 {
151 List *stmts;
152 char *end_label;
153 int end_label_location;
154 } loop_body;
155 List *list;
156 PLpgSQL_type *dtype;
157 PLpgSQL_datum *datum;
158 PLpgSQL_var *var;
159 PLpgSQL_expr *expr;
160 PLpgSQL_stmt *stmt;
161 PLpgSQL_condition *condition;
162 PLpgSQL_exception *exception;
163 PLpgSQL_exception_block *exception_block;
164 PLpgSQL_nsitem *nsitem;
165 PLpgSQL_diag_item *diagitem;
166 PLpgSQL_stmt_fetch *fetch;
167 PLpgSQL_case_when *casewhen;
168 }
169
170 %type <declhdr> decl_sect
171 %type <varname> decl_varname
172 %type <boolean> decl_const decl_notnull exit_type
173 %type <expr> decl_defval decl_cursor_query
174 %type <dtype> decl_datatype
175 %type <oid> decl_collate
176 %type <datum> decl_cursor_args
177 %type <list> decl_cursor_arglist
178 %type <nsitem> decl_aliasitem
179
180 %type <expr> expr_until_semi
181 %type <expr> expr_until_then expr_until_loop opt_expr_until_when
182 %type <expr> opt_exitcond
183
184 %type <var> cursor_variable
185 %type <datum> decl_cursor_arg
186 %type <forvariable> for_variable
187 %type <ival> foreach_slice
188 %type <stmt> for_control
189
190 %type <str> any_identifier opt_block_label opt_loop_label opt_label
191 %type <str> option_value
192
193 %type <list> proc_sect stmt_elsifs stmt_else
194 %type <loop_body> loop_body
195 %type <stmt> proc_stmt pl_block
196 %type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
197 %type <stmt> stmt_return stmt_raise stmt_assert stmt_execsql
198 %type <stmt> stmt_dynexecute stmt_for stmt_perform stmt_call stmt_getdiag
199 %type <stmt> stmt_open stmt_fetch stmt_move stmt_close stmt_null
200 %type <stmt> stmt_commit stmt_rollback
201 %type <stmt> stmt_case stmt_foreach_a
202
203 %type <list> proc_exceptions
204 %type <exception_block> exception_sect
205 %type <exception> proc_exception
206 %type <condition> proc_conditions proc_condition
207
208 %type <casewhen> case_when
209 %type <list> case_when_list opt_case_else
210
211 %type <boolean> getdiag_area_opt
212 %type <list> getdiag_list
213 %type <diagitem> getdiag_list_item
214 %type <datum> getdiag_target
215 %type <ival> getdiag_item
216
217 %type <ival> opt_scrollable
218 %type <fetch> opt_fetch_direction
219
220 %type <ival> opt_transaction_chain
221
222 %type <keyword> unreserved_keyword
223
224
225 /*
226 * Basic non-keyword token types. These are hard-wired into the core lexer.
227 * They must be listed first so that their numeric codes do not depend on
228 * the set of keywords. Keep this list in sync with backend/parser/gram.y!
229 *
230 * Some of these are not directly referenced in this file, but they must be
231 * here anyway.
232 */
233 %token <str> IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op
234 %token <ival> ICONST PARAM
235 %token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER
236 %token LESS_EQUALS GREATER_EQUALS NOT_EQUALS
237
238 /*
239 * Other tokens recognized by plpgsql's lexer interface layer (pl_scanner.c).
240 */
241 %token <word> T_WORD /* unrecognized simple identifier */
242 %token <cword> T_CWORD /* unrecognized composite identifier */
243 %token <wdatum> T_DATUM /* a VAR, ROW, REC, or RECFIELD variable */
244 %token LESS_LESS
245 %token GREATER_GREATER
246
247 /*
248 * Keyword tokens. Some of these are reserved and some are not;
249 * see pl_scanner.c for info. Be sure unreserved keywords are listed
250 * in the "unreserved_keyword" production below.
251 */
252 %token <keyword> K_ABSOLUTE
253 %token <keyword> K_ALIAS
254 %token <keyword> K_ALL
255 %token <keyword> K_AND
256 %token <keyword> K_ARRAY
257 %token <keyword> K_ASSERT
258 %token <keyword> K_BACKWARD
259 %token <keyword> K_BEGIN
260 %token <keyword> K_BY
261 %token <keyword> K_CALL
262 %token <keyword> K_CASE
263 %token <keyword> K_CHAIN
264 %token <keyword> K_CLOSE
265 %token <keyword> K_COLLATE
266 %token <keyword> K_COLUMN
267 %token <keyword> K_COLUMN_NAME
268 %token <keyword> K_COMMIT
269 %token <keyword> K_CONSTANT
270 %token <keyword> K_CONSTRAINT
271 %token <keyword> K_CONSTRAINT_NAME
272 %token <keyword> K_CONTINUE
273 %token <keyword> K_CURRENT
274 %token <keyword> K_CURSOR
275 %token <keyword> K_DATATYPE
276 %token <keyword> K_DEBUG
277 %token <keyword> K_DECLARE
278 %token <keyword> K_DEFAULT
279 %token <keyword> K_DETAIL
280 %token <keyword> K_DIAGNOSTICS
281 %token <keyword> K_DO
282 %token <keyword> K_DUMP
283 %token <keyword> K_ELSE
284 %token <keyword> K_ELSIF
285 %token <keyword> K_END
286 %token <keyword> K_ERRCODE
287 %token <keyword> K_ERROR
288 %token <keyword> K_EXCEPTION
289 %token <keyword> K_EXECUTE
290 %token <keyword> K_EXIT
291 %token <keyword> K_FETCH
292 %token <keyword> K_FIRST
293 %token <keyword> K_FOR
294 %token <keyword> K_FOREACH
295 %token <keyword> K_FORWARD
296 %token <keyword> K_FROM
297 %token <keyword> K_GET
298 %token <keyword> K_HINT
299 %token <keyword> K_IF
300 %token <keyword> K_IMPORT
301 %token <keyword> K_IN
302 %token <keyword> K_INFO
303 %token <keyword> K_INSERT
304 %token <keyword> K_INTO
305 %token <keyword> K_IS
306 %token <keyword> K_LAST
307 %token <keyword> K_LOG
308 %token <keyword> K_LOOP
309 %token <keyword> K_MESSAGE
310 %token <keyword> K_MESSAGE_TEXT
311 %token <keyword> K_MOVE
312 %token <keyword> K_NEXT
313 %token <keyword> K_NO
314 %token <keyword> K_NOT
315 %token <keyword> K_NOTICE
316 %token <keyword> K_NULL
317 %token <keyword> K_OPEN
318 %token <keyword> K_OPTION
319 %token <keyword> K_OR
320 %token <keyword> K_PERFORM
321 %token <keyword> K_PG_CONTEXT
322 %token <keyword> K_PG_DATATYPE_NAME
323 %token <keyword> K_PG_EXCEPTION_CONTEXT
324 %token <keyword> K_PG_EXCEPTION_DETAIL
325 %token <keyword> K_PG_EXCEPTION_HINT
326 %token <keyword> K_PRINT_STRICT_PARAMS
327 %token <keyword> K_PRIOR
328 %token <keyword> K_QUERY
329 %token <keyword> K_RAISE
330 %token <keyword> K_RELATIVE
331 %token <keyword> K_RETURN
332 %token <keyword> K_RETURNED_SQLSTATE
333 %token <keyword> K_REVERSE
334 %token <keyword> K_ROLLBACK
335 %token <keyword> K_ROW_COUNT
336 %token <keyword> K_ROWTYPE
337 %token <keyword> K_SCHEMA
338 %token <keyword> K_SCHEMA_NAME
339 %token <keyword> K_SCROLL
340 %token <keyword> K_SLICE
341 %token <keyword> K_SQLSTATE
342 %token <keyword> K_STACKED
343 %token <keyword> K_STRICT
344 %token <keyword> K_TABLE
345 %token <keyword> K_TABLE_NAME
346 %token <keyword> K_THEN
347 %token <keyword> K_TO
348 %token <keyword> K_TYPE
349 %token <keyword> K_USE_COLUMN
350 %token <keyword> K_USE_VARIABLE
351 %token <keyword> K_USING
352 %token <keyword> K_VARIABLE_CONFLICT
353 %token <keyword> K_WARNING
354 %token <keyword> K_WHEN
355 %token <keyword> K_WHILE
356
357 %%
358
359 pl_function : comp_options pl_block opt_semi
360 {
361 plpgsql_parse_result = (PLpgSQL_stmt_block *) $2;
362 }
363 ;
364
365 comp_options :
366 | comp_options comp_option
367 ;
368
369 comp_option : '#' K_OPTION K_DUMP
370 {
371 plpgsql_DumpExecTree = true;
372 }
373 | '#' K_PRINT_STRICT_PARAMS option_value
374 {
375 if (strcmp($3, "on") == 0)
376 plpgsql_curr_compile->print_strict_params = true;
377 else if (strcmp($3, "off") == 0)
378 plpgsql_curr_compile->print_strict_params = false;
379 else
380 elog(ERROR, "unrecognized print_strict_params option %s", $3);
381 }
382 | '#' K_VARIABLE_CONFLICT K_ERROR
383 {
384 plpgsql_curr_compile->resolve_option = PLPGSQL_RESOLVE_ERROR;
385 }
386 | '#' K_VARIABLE_CONFLICT K_USE_VARIABLE
387 {
388 plpgsql_curr_compile->resolve_option = PLPGSQL_RESOLVE_VARIABLE;
389 }
390 | '#' K_VARIABLE_CONFLICT K_USE_COLUMN
391 {
392 plpgsql_curr_compile->resolve_option = PLPGSQL_RESOLVE_COLUMN;
393 }
394 ;
395
396 option_value : T_WORD
397 {
398 $$ = $1.ident;
399 }
400 | unreserved_keyword
401 {
402 $$ = pstrdup($1);
403 }
404
405 opt_semi :
406 | ';'
407 ;
408
409 pl_block : decl_sect K_BEGIN proc_sect exception_sect K_END opt_label
410 {
411 PLpgSQL_stmt_block *new;
412
413 new = palloc0(sizeof(PLpgSQL_stmt_block));
414
415 new->cmd_type = PLPGSQL_STMT_BLOCK;
416 new->lineno = plpgsql_location_to_lineno(@2);
417 new->stmtid = ++plpgsql_curr_compile->nstatements;
418 new->label = $1.label;
419 new->n_initvars = $1.n_initvars;
420 new->initvarnos = $1.initvarnos;
421 new->body = $3;
422 new->exceptions = $4;
423
424 check_labels($1.label, $6, @6);
425 plpgsql_ns_pop();
426
427 $$ = (PLpgSQL_stmt *)new;
428 }
429 ;
430
431
432 decl_sect : opt_block_label
433 {
434 /* done with decls, so resume identifier lookup */
435 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
436 $$.label = $1;
437 $$.n_initvars = 0;
438 $$.initvarnos = NULL;
439 }
440 | opt_block_label decl_start
441 {
442 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
443 $$.label = $1;
444 $$.n_initvars = 0;
445 $$.initvarnos = NULL;
446 }
447 | opt_block_label decl_start decl_stmts
448 {
449 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
450 $$.label = $1;
451 /* Remember variables declared in decl_stmts */
452 $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
453 }
454 ;
455
456 decl_start : K_DECLARE
457 {
458 /* Forget any variables created before block */
459 plpgsql_add_initdatums(NULL);
460 /*
461 * Disable scanner lookup of identifiers while
462 * we process the decl_stmts
463 */
464 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_DECLARE;
465 }
466 ;
467
468 decl_stmts : decl_stmts decl_stmt
469 | decl_stmt
470 ;
471
472 decl_stmt : decl_statement
473 | K_DECLARE
474 {
475 /* We allow useless extra DECLAREs */
476 }
477 | LESS_LESS any_identifier GREATER_GREATER
478 {
479 /*
480 * Throw a helpful error if user tries to put block
481 * label just before BEGIN, instead of before DECLARE.
482 */
483 ereport(ERROR,
484 (errcode(ERRCODE_SYNTAX_ERROR),
485 errmsg("block label must be placed before DECLARE, not after"),
486 parser_errposition(@1)));
487 }
488 ;
489
490 decl_statement : decl_varname decl_const decl_datatype decl_collate decl_notnull decl_defval
491 {
492 PLpgSQL_variable *var;
493
494 /*
495 * If a collation is supplied, insert it into the
496 * datatype. We assume decl_datatype always returns
497 * a freshly built struct not shared with other
498 * variables.
499 */
500 if (OidIsValid($4))
501 {
502 if (!OidIsValid($3->collation))
503 ereport(ERROR,
504 (errcode(ERRCODE_DATATYPE_MISMATCH),
505 errmsg("collations are not supported by type %s",
506 format_type_be($3->typoid)),
507 parser_errposition(@4)));
508 $3->collation = $4;
509 }
510
511 var = plpgsql_build_variable($1.name, $1.lineno,
512 $3, true);
513 var->isconst = $2;
514 var->notnull = $5;
515 var->default_val = $6;
516
517 /*
518 * The combination of NOT NULL without an initializer
519 * can't work, so let's reject it at compile time.
520 */
521 if (var->notnull && var->default_val == NULL)
522 ereport(ERROR,
523 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
524 errmsg("variable \"%s\" must have a default value, since it's declared NOT NULL",
525 var->refname),
526 parser_errposition(@5)));
527 }
528 | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
529 {
530 plpgsql_ns_additem($4->itemtype,
531 $4->itemno, $1.name);
532 }
533 | decl_varname opt_scrollable K_CURSOR
534 { plpgsql_ns_push($1.name, PLPGSQL_LABEL_OTHER); }
535 decl_cursor_args decl_is_for decl_cursor_query
536 {
537 PLpgSQL_var *new;
538 PLpgSQL_expr *curname_def;
539 char buf[NAMEDATALEN * 2 + 64];
540 char *cp1;
541 char *cp2;
542
543 /* pop local namespace for cursor args */
544 plpgsql_ns_pop();
545
546 new = (PLpgSQL_var *)
547 plpgsql_build_variable($1.name, $1.lineno,
548 plpgsql_build_datatype(REFCURSOROID,
549 -1,
550 InvalidOid,
551 NULL),
552 true);
553
554 curname_def = palloc0(sizeof(PLpgSQL_expr));
555
556 /* Note: refname has been truncated to NAMEDATALEN */
557 cp1 = new->refname;
558 cp2 = buf;
559 /*
560 * Don't trust standard_conforming_strings here;
561 * it might change before we use the string.
562 */
563 if (strchr(cp1, '\\') != NULL)
564 *cp2++ = ESCAPE_STRING_SYNTAX;
565 *cp2++ = '\'';
566 while (*cp1)
567 {
568 if (SQL_STR_DOUBLE(*cp1, true))
569 *cp2++ = *cp1;
570 *cp2++ = *cp1++;
571 }
572 strcpy(cp2, "'::pg_catalog.refcursor");
573 curname_def->query = pstrdup(buf);
574 curname_def->parseMode = RAW_PARSE_PLPGSQL_EXPR;
575 new->default_val = curname_def;
576
577 new->cursor_explicit_expr = $7;
578 if ($5 == NULL)
579 new->cursor_explicit_argrow = -1;
580 else
581 new->cursor_explicit_argrow = $5->dno;
582 new->cursor_options = CURSOR_OPT_FAST_PLAN | $2;
583 }
584 ;
585
586 opt_scrollable :
587 {
588 $$ = 0;
589 }
590 | K_NO K_SCROLL
591 {
592 $$ = CURSOR_OPT_NO_SCROLL;
593 }
594 | K_SCROLL
595 {
596 $$ = CURSOR_OPT_SCROLL;
597 }
598 ;
599
600 decl_cursor_query :
601 {
602 $$ = read_sql_stmt();
603 }
604 ;
605
606 decl_cursor_args :
607 {
608 $$ = NULL;
609 }
610 | '(' decl_cursor_arglist ')'
611 {
612 PLpgSQL_row *new;
613 int i;
614 ListCell *l;
615
616 new = palloc0(sizeof(PLpgSQL_row));
617 new->dtype = PLPGSQL_DTYPE_ROW;
618 new->refname = "(unnamed row)";
619 new->lineno = plpgsql_location_to_lineno(@1);
620 new->rowtupdesc = NULL;
621 new->nfields = list_length($2);
622 new->fieldnames = palloc(new->nfields * sizeof(char *));
623 new->varnos = palloc(new->nfields * sizeof(int));
624
625 i = 0;
foreach(l,$2)626 foreach (l, $2)
627 {
628 PLpgSQL_variable *arg = (PLpgSQL_variable *) lfirst(l);
629 Assert(!arg->isconst);
630 new->fieldnames[i] = arg->refname;
631 new->varnos[i] = arg->dno;
632 i++;
633 }
634 list_free($2);
635
636 plpgsql_adddatum((PLpgSQL_datum *) new);
637 $$ = (PLpgSQL_datum *) new;
638 }
639 ;
640
641 decl_cursor_arglist : decl_cursor_arg
642 {
643 $$ = list_make1($1);
644 }
645 | decl_cursor_arglist ',' decl_cursor_arg
646 {
647 $$ = lappend($1, $3);
648 }
649 ;
650
651 decl_cursor_arg : decl_varname decl_datatype
652 {
653 $$ = (PLpgSQL_datum *)
654 plpgsql_build_variable($1.name, $1.lineno,
655 $2, true);
656 }
657 ;
658
659 decl_is_for : K_IS | /* Oracle */
660 K_FOR; /* SQL standard */
661
662 decl_aliasitem : T_WORD
663 {
664 PLpgSQL_nsitem *nsi;
665
666 nsi = plpgsql_ns_lookup(plpgsql_ns_top(), false,
667 $1.ident, NULL, NULL,
668 NULL);
669 if (nsi == NULL)
670 ereport(ERROR,
671 (errcode(ERRCODE_UNDEFINED_OBJECT),
672 errmsg("variable \"%s\" does not exist",
673 $1.ident),
674 parser_errposition(@1)));
675 $$ = nsi;
676 }
677 | unreserved_keyword
678 {
679 PLpgSQL_nsitem *nsi;
680
681 nsi = plpgsql_ns_lookup(plpgsql_ns_top(), false,
682 $1, NULL, NULL,
683 NULL);
684 if (nsi == NULL)
685 ereport(ERROR,
686 (errcode(ERRCODE_UNDEFINED_OBJECT),
687 errmsg("variable \"%s\" does not exist",
688 $1),
689 parser_errposition(@1)));
690 $$ = nsi;
691 }
692 | T_CWORD
693 {
694 PLpgSQL_nsitem *nsi;
695
696 if (list_length($1.idents) == 2)
697 nsi = plpgsql_ns_lookup(plpgsql_ns_top(), false,
698 strVal(linitial($1.idents)),
699 strVal(lsecond($1.idents)),
700 NULL,
701 NULL);
702 else if (list_length($1.idents) == 3)
703 nsi = plpgsql_ns_lookup(plpgsql_ns_top(), false,
704 strVal(linitial($1.idents)),
705 strVal(lsecond($1.idents)),
706 strVal(lthird($1.idents)),
707 NULL);
708 else
709 nsi = NULL;
710 if (nsi == NULL)
711 ereport(ERROR,
712 (errcode(ERRCODE_UNDEFINED_OBJECT),
713 errmsg("variable \"%s\" does not exist",
714 NameListToString($1.idents)),
715 parser_errposition(@1)));
716 $$ = nsi;
717 }
718 ;
719
720 decl_varname : T_WORD
721 {
722 $$.name = $1.ident;
723 $$.lineno = plpgsql_location_to_lineno(@1);
724 /*
725 * Check to make sure name isn't already declared
726 * in the current block.
727 */
728 if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
729 $1.ident, NULL, NULL,
730 NULL) != NULL)
731 yyerror("duplicate declaration");
732
733 if (plpgsql_curr_compile->extra_warnings & PLPGSQL_XCHECK_SHADOWVAR ||
734 plpgsql_curr_compile->extra_errors & PLPGSQL_XCHECK_SHADOWVAR)
735 {
736 PLpgSQL_nsitem *nsi;
737 nsi = plpgsql_ns_lookup(plpgsql_ns_top(), false,
738 $1.ident, NULL, NULL, NULL);
739 if (nsi != NULL)
740 ereport(plpgsql_curr_compile->extra_errors & PLPGSQL_XCHECK_SHADOWVAR ? ERROR : WARNING,
741 (errcode(ERRCODE_DUPLICATE_ALIAS),
742 errmsg("variable \"%s\" shadows a previously defined variable",
743 $1.ident),
744 parser_errposition(@1)));
745 }
746
747 }
748 | unreserved_keyword
749 {
750 $$.name = pstrdup($1);
751 $$.lineno = plpgsql_location_to_lineno(@1);
752 /*
753 * Check to make sure name isn't already declared
754 * in the current block.
755 */
756 if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
757 $1, NULL, NULL,
758 NULL) != NULL)
759 yyerror("duplicate declaration");
760
761 if (plpgsql_curr_compile->extra_warnings & PLPGSQL_XCHECK_SHADOWVAR ||
762 plpgsql_curr_compile->extra_errors & PLPGSQL_XCHECK_SHADOWVAR)
763 {
764 PLpgSQL_nsitem *nsi;
765 nsi = plpgsql_ns_lookup(plpgsql_ns_top(), false,
766 $1, NULL, NULL, NULL);
767 if (nsi != NULL)
768 ereport(plpgsql_curr_compile->extra_errors & PLPGSQL_XCHECK_SHADOWVAR ? ERROR : WARNING,
769 (errcode(ERRCODE_DUPLICATE_ALIAS),
770 errmsg("variable \"%s\" shadows a previously defined variable",
771 $1),
772 parser_errposition(@1)));
773 }
774
775 }
776 ;
777
778 decl_const :
779 { $$ = false; }
780 | K_CONSTANT
781 { $$ = true; }
782 ;
783
784 decl_datatype :
785 {
786 /*
787 * If there's a lookahead token, read_datatype
788 * should consume it.
789 */
790 $$ = read_datatype(yychar);
791 yyclearin;
792 }
793 ;
794
795 decl_collate :
796 { $$ = InvalidOid; }
797 | K_COLLATE T_WORD
798 {
799 $$ = get_collation_oid(list_make1(makeString($2.ident)),
800 false);
801 }
802 | K_COLLATE unreserved_keyword
803 {
804 $$ = get_collation_oid(list_make1(makeString(pstrdup($2))),
805 false);
806 }
807 | K_COLLATE T_CWORD
808 {
809 $$ = get_collation_oid($2.idents, false);
810 }
811 ;
812
813 decl_notnull :
814 { $$ = false; }
815 | K_NOT K_NULL
816 { $$ = true; }
817 ;
818
819 decl_defval : ';'
820 { $$ = NULL; }
821 | decl_defkey
822 {
823 $$ = read_sql_expression(';', ";");
824 }
825 ;
826
827 decl_defkey : assign_operator
828 | K_DEFAULT
829 ;
830
831 /*
832 * Ada-based PL/SQL uses := for assignment and variable defaults, while
833 * the SQL standard uses equals for these cases and for GET
834 * DIAGNOSTICS, so we support both. FOR and OPEN only support :=.
835 */
836 assign_operator : '='
837 | COLON_EQUALS
838 ;
839
840 proc_sect :
841 { $$ = NIL; }
842 | proc_sect proc_stmt
843 {
844 /* don't bother linking null statements into list */
845 if ($2 == NULL)
846 $$ = $1;
847 else
848 $$ = lappend($1, $2);
849 }
850 ;
851
852 proc_stmt : pl_block ';'
853 { $$ = $1; }
854 | stmt_assign
855 { $$ = $1; }
856 | stmt_if
857 { $$ = $1; }
858 | stmt_case
859 { $$ = $1; }
860 | stmt_loop
861 { $$ = $1; }
862 | stmt_while
863 { $$ = $1; }
864 | stmt_for
865 { $$ = $1; }
866 | stmt_foreach_a
867 { $$ = $1; }
868 | stmt_exit
869 { $$ = $1; }
870 | stmt_return
871 { $$ = $1; }
872 | stmt_raise
873 { $$ = $1; }
874 | stmt_assert
875 { $$ = $1; }
876 | stmt_execsql
877 { $$ = $1; }
878 | stmt_dynexecute
879 { $$ = $1; }
880 | stmt_perform
881 { $$ = $1; }
882 | stmt_call
883 { $$ = $1; }
884 | stmt_getdiag
885 { $$ = $1; }
886 | stmt_open
887 { $$ = $1; }
888 | stmt_fetch
889 { $$ = $1; }
890 | stmt_move
891 { $$ = $1; }
892 | stmt_close
893 { $$ = $1; }
894 | stmt_null
895 { $$ = $1; }
896 | stmt_commit
897 { $$ = $1; }
898 | stmt_rollback
899 { $$ = $1; }
900 ;
901
902 stmt_perform : K_PERFORM
903 {
904 PLpgSQL_stmt_perform *new;
905 int startloc;
906
907 new = palloc0(sizeof(PLpgSQL_stmt_perform));
908 new->cmd_type = PLPGSQL_STMT_PERFORM;
909 new->lineno = plpgsql_location_to_lineno(@1);
910 new->stmtid = ++plpgsql_curr_compile->nstatements;
911 plpgsql_push_back_token(K_PERFORM);
912
913 /*
914 * Since PERFORM isn't legal SQL, we have to cheat to
915 * the extent of substituting "SELECT" for "PERFORM"
916 * in the parsed text. It does not seem worth
917 * inventing a separate parse mode for this one case.
918 * We can't do syntax-checking until after we make the
919 * substitution.
920 */
921 new->expr = read_sql_construct(';', 0, 0, ";",
922 RAW_PARSE_DEFAULT,
923 false, false, true,
924 &startloc, NULL);
925 /* overwrite "perform" ... */
926 memcpy(new->expr->query, " SELECT", 7);
927 /* left-justify to get rid of the leading space */
928 memmove(new->expr->query, new->expr->query + 1,
929 strlen(new->expr->query));
930 /* offset syntax error position to account for that */
931 check_sql_expr(new->expr->query, new->expr->parseMode,
932 startloc + 1);
933
934 $$ = (PLpgSQL_stmt *)new;
935 }
936 ;
937
938 stmt_call : K_CALL
939 {
940 PLpgSQL_stmt_call *new;
941
942 new = palloc0(sizeof(PLpgSQL_stmt_call));
943 new->cmd_type = PLPGSQL_STMT_CALL;
944 new->lineno = plpgsql_location_to_lineno(@1);
945 new->stmtid = ++plpgsql_curr_compile->nstatements;
946 plpgsql_push_back_token(K_CALL);
947 new->expr = read_sql_stmt();
948 new->is_call = true;
949
950 /* Remember we may need a procedure resource owner */
951 plpgsql_curr_compile->requires_procedure_resowner = true;
952
953 $$ = (PLpgSQL_stmt *)new;
954
955 }
956 | K_DO
957 {
958 /* use the same structures as for CALL, for simplicity */
959 PLpgSQL_stmt_call *new;
960
961 new = palloc0(sizeof(PLpgSQL_stmt_call));
962 new->cmd_type = PLPGSQL_STMT_CALL;
963 new->lineno = plpgsql_location_to_lineno(@1);
964 new->stmtid = ++plpgsql_curr_compile->nstatements;
965 plpgsql_push_back_token(K_DO);
966 new->expr = read_sql_stmt();
967 new->is_call = false;
968
969 /* Remember we may need a procedure resource owner */
970 plpgsql_curr_compile->requires_procedure_resowner = true;
971
972 $$ = (PLpgSQL_stmt *)new;
973
974 }
975 ;
976
977 stmt_assign : T_DATUM
978 {
979 PLpgSQL_stmt_assign *new;
980 RawParseMode pmode;
981
982 /* see how many names identify the datum */
983 switch ($1.ident ? 1 : list_length($1.idents))
984 {
985 case 1:
986 pmode = RAW_PARSE_PLPGSQL_ASSIGN1;
987 break;
988 case 2:
989 pmode = RAW_PARSE_PLPGSQL_ASSIGN2;
990 break;
991 case 3:
992 pmode = RAW_PARSE_PLPGSQL_ASSIGN3;
993 break;
994 default:
995 elog(ERROR, "unexpected number of names");
996 pmode = 0; /* keep compiler quiet */
997 }
998
999 check_assignable($1.datum, @1);
1000 new = palloc0(sizeof(PLpgSQL_stmt_assign));
1001 new->cmd_type = PLPGSQL_STMT_ASSIGN;
1002 new->lineno = plpgsql_location_to_lineno(@1);
1003 new->stmtid = ++plpgsql_curr_compile->nstatements;
1004 new->varno = $1.datum->dno;
1005 /* Push back the head name to include it in the stmt */
1006 plpgsql_push_back_token(T_DATUM);
1007 new->expr = read_sql_construct(';', 0, 0, ";",
1008 pmode,
1009 false, true, true,
1010 NULL, NULL);
1011
1012 $$ = (PLpgSQL_stmt *)new;
1013 }
1014 ;
1015
1016 stmt_getdiag : K_GET getdiag_area_opt K_DIAGNOSTICS getdiag_list ';'
1017 {
1018 PLpgSQL_stmt_getdiag *new;
1019 ListCell *lc;
1020
1021 new = palloc0(sizeof(PLpgSQL_stmt_getdiag));
1022 new->cmd_type = PLPGSQL_STMT_GETDIAG;
1023 new->lineno = plpgsql_location_to_lineno(@1);
1024 new->stmtid = ++plpgsql_curr_compile->nstatements;
1025 new->is_stacked = $2;
1026 new->diag_items = $4;
1027
1028 /*
1029 * Check information items are valid for area option.
1030 */
1031 foreach(lc, new->diag_items)
1032 {
1033 PLpgSQL_diag_item *ditem = (PLpgSQL_diag_item *) lfirst(lc);
1034
1035 switch (ditem->kind)
1036 {
1037 /* these fields are disallowed in stacked case */
1038 case PLPGSQL_GETDIAG_ROW_COUNT:
1039 if (new->is_stacked)
1040 ereport(ERROR,
1041 (errcode(ERRCODE_SYNTAX_ERROR),
1042 errmsg("diagnostics item %s is not allowed in GET STACKED DIAGNOSTICS",
1043 plpgsql_getdiag_kindname(ditem->kind)),
1044 parser_errposition(@1)));
1045 break;
1046 /* these fields are disallowed in current case */
1047 case PLPGSQL_GETDIAG_ERROR_CONTEXT:
1048 case PLPGSQL_GETDIAG_ERROR_DETAIL:
1049 case PLPGSQL_GETDIAG_ERROR_HINT:
1050 case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
1051 case PLPGSQL_GETDIAG_COLUMN_NAME:
1052 case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
1053 case PLPGSQL_GETDIAG_DATATYPE_NAME:
1054 case PLPGSQL_GETDIAG_MESSAGE_TEXT:
1055 case PLPGSQL_GETDIAG_TABLE_NAME:
1056 case PLPGSQL_GETDIAG_SCHEMA_NAME:
1057 if (!new->is_stacked)
1058 ereport(ERROR,
1059 (errcode(ERRCODE_SYNTAX_ERROR),
1060 errmsg("diagnostics item %s is not allowed in GET CURRENT DIAGNOSTICS",
1061 plpgsql_getdiag_kindname(ditem->kind)),
1062 parser_errposition(@1)));
1063 break;
1064 /* these fields are allowed in either case */
1065 case PLPGSQL_GETDIAG_CONTEXT:
1066 break;
1067 default:
1068 elog(ERROR, "unrecognized diagnostic item kind: %d",
1069 ditem->kind);
1070 break;
1071 }
1072 }
1073
1074 $$ = (PLpgSQL_stmt *)new;
1075 }
1076 ;
1077
1078 getdiag_area_opt :
1079 {
1080 $$ = false;
1081 }
1082 | K_CURRENT
1083 {
1084 $$ = false;
1085 }
1086 | K_STACKED
1087 {
1088 $$ = true;
1089 }
1090 ;
1091
1092 getdiag_list : getdiag_list ',' getdiag_list_item
1093 {
1094 $$ = lappend($1, $3);
1095 }
1096 | getdiag_list_item
1097 {
1098 $$ = list_make1($1);
1099 }
1100 ;
1101
1102 getdiag_list_item : getdiag_target assign_operator getdiag_item
1103 {
1104 PLpgSQL_diag_item *new;
1105
1106 new = palloc(sizeof(PLpgSQL_diag_item));
1107 new->target = $1->dno;
1108 new->kind = $3;
1109
1110 $$ = new;
1111 }
1112 ;
1113
1114 getdiag_item :
1115 {
1116 int tok = yylex();
1117
1118 if (tok_is_keyword(tok, &yylval,
1119 K_ROW_COUNT, "row_count"))
1120 $$ = PLPGSQL_GETDIAG_ROW_COUNT;
1121 else if (tok_is_keyword(tok, &yylval,
1122 K_PG_CONTEXT, "pg_context"))
1123 $$ = PLPGSQL_GETDIAG_CONTEXT;
1124 else if (tok_is_keyword(tok, &yylval,
1125 K_PG_EXCEPTION_DETAIL, "pg_exception_detail"))
1126 $$ = PLPGSQL_GETDIAG_ERROR_DETAIL;
1127 else if (tok_is_keyword(tok, &yylval,
1128 K_PG_EXCEPTION_HINT, "pg_exception_hint"))
1129 $$ = PLPGSQL_GETDIAG_ERROR_HINT;
1130 else if (tok_is_keyword(tok, &yylval,
1131 K_PG_EXCEPTION_CONTEXT, "pg_exception_context"))
1132 $$ = PLPGSQL_GETDIAG_ERROR_CONTEXT;
1133 else if (tok_is_keyword(tok, &yylval,
1134 K_COLUMN_NAME, "column_name"))
1135 $$ = PLPGSQL_GETDIAG_COLUMN_NAME;
1136 else if (tok_is_keyword(tok, &yylval,
1137 K_CONSTRAINT_NAME, "constraint_name"))
1138 $$ = PLPGSQL_GETDIAG_CONSTRAINT_NAME;
1139 else if (tok_is_keyword(tok, &yylval,
1140 K_PG_DATATYPE_NAME, "pg_datatype_name"))
1141 $$ = PLPGSQL_GETDIAG_DATATYPE_NAME;
1142 else if (tok_is_keyword(tok, &yylval,
1143 K_MESSAGE_TEXT, "message_text"))
1144 $$ = PLPGSQL_GETDIAG_MESSAGE_TEXT;
1145 else if (tok_is_keyword(tok, &yylval,
1146 K_TABLE_NAME, "table_name"))
1147 $$ = PLPGSQL_GETDIAG_TABLE_NAME;
1148 else if (tok_is_keyword(tok, &yylval,
1149 K_SCHEMA_NAME, "schema_name"))
1150 $$ = PLPGSQL_GETDIAG_SCHEMA_NAME;
1151 else if (tok_is_keyword(tok, &yylval,
1152 K_RETURNED_SQLSTATE, "returned_sqlstate"))
1153 $$ = PLPGSQL_GETDIAG_RETURNED_SQLSTATE;
1154 else
1155 yyerror("unrecognized GET DIAGNOSTICS item");
1156 }
1157 ;
1158
1159 getdiag_target : T_DATUM
1160 {
1161 /*
1162 * In principle we should support a getdiag_target
1163 * that is an array element, but for now we don't, so
1164 * just throw an error if next token is '['.
1165 */
1166 if ($1.datum->dtype == PLPGSQL_DTYPE_ROW ||
1167 $1.datum->dtype == PLPGSQL_DTYPE_REC ||
1168 plpgsql_peek() == '[')
1169 ereport(ERROR,
1170 (errcode(ERRCODE_SYNTAX_ERROR),
1171 errmsg("\"%s\" is not a scalar variable",
1172 NameOfDatum(&($1))),
1173 parser_errposition(@1)));
1174 check_assignable($1.datum, @1);
1175 $$ = $1.datum;
1176 }
1177 | T_WORD
1178 {
1179 /* just to give a better message than "syntax error" */
1180 word_is_not_variable(&($1), @1);
1181 }
1182 | T_CWORD
1183 {
1184 /* just to give a better message than "syntax error" */
1185 cword_is_not_variable(&($1), @1);
1186 }
1187 ;
1188
1189 stmt_if : K_IF expr_until_then proc_sect stmt_elsifs stmt_else K_END K_IF ';'
1190 {
1191 PLpgSQL_stmt_if *new;
1192
1193 new = palloc0(sizeof(PLpgSQL_stmt_if));
1194 new->cmd_type = PLPGSQL_STMT_IF;
1195 new->lineno = plpgsql_location_to_lineno(@1);
1196 new->stmtid = ++plpgsql_curr_compile->nstatements;
1197 new->cond = $2;
1198 new->then_body = $3;
1199 new->elsif_list = $4;
1200 new->else_body = $5;
1201
1202 $$ = (PLpgSQL_stmt *)new;
1203 }
1204 ;
1205
1206 stmt_elsifs :
1207 {
1208 $$ = NIL;
1209 }
1210 | stmt_elsifs K_ELSIF expr_until_then proc_sect
1211 {
1212 PLpgSQL_if_elsif *new;
1213
1214 new = palloc0(sizeof(PLpgSQL_if_elsif));
1215 new->lineno = plpgsql_location_to_lineno(@2);
1216 new->cond = $3;
1217 new->stmts = $4;
1218
1219 $$ = lappend($1, new);
1220 }
1221 ;
1222
1223 stmt_else :
1224 {
1225 $$ = NIL;
1226 }
1227 | K_ELSE proc_sect
1228 {
1229 $$ = $2;
1230 }
1231 ;
1232
1233 stmt_case : K_CASE opt_expr_until_when case_when_list opt_case_else K_END K_CASE ';'
1234 {
1235 $$ = make_case(@1, $2, $3, $4);
1236 }
1237 ;
1238
1239 opt_expr_until_when :
1240 {
1241 PLpgSQL_expr *expr = NULL;
1242 int tok = yylex();
1243
1244 if (tok != K_WHEN)
1245 {
1246 plpgsql_push_back_token(tok);
1247 expr = read_sql_expression(K_WHEN, "WHEN");
1248 }
1249 plpgsql_push_back_token(K_WHEN);
1250 $$ = expr;
1251 }
1252 ;
1253
1254 case_when_list : case_when_list case_when
1255 {
1256 $$ = lappend($1, $2);
1257 }
1258 | case_when
1259 {
1260 $$ = list_make1($1);
1261 }
1262 ;
1263
1264 case_when : K_WHEN expr_until_then proc_sect
1265 {
1266 PLpgSQL_case_when *new = palloc(sizeof(PLpgSQL_case_when));
1267
1268 new->lineno = plpgsql_location_to_lineno(@1);
1269 new->expr = $2;
1270 new->stmts = $3;
1271 $$ = new;
1272 }
1273 ;
1274
1275 opt_case_else :
1276 {
1277 $$ = NIL;
1278 }
1279 | K_ELSE proc_sect
1280 {
1281 /*
1282 * proc_sect could return an empty list, but we
1283 * must distinguish that from not having ELSE at all.
1284 * Simplest fix is to return a list with one NULL
1285 * pointer, which make_case() must take care of.
1286 */
1287 if ($2 != NIL)
1288 $$ = $2;
1289 else
1290 $$ = list_make1(NULL);
1291 }
1292 ;
1293
1294 stmt_loop : opt_loop_label K_LOOP loop_body
1295 {
1296 PLpgSQL_stmt_loop *new;
1297
1298 new = palloc0(sizeof(PLpgSQL_stmt_loop));
1299 new->cmd_type = PLPGSQL_STMT_LOOP;
1300 new->lineno = plpgsql_location_to_lineno(@2);
1301 new->stmtid = ++plpgsql_curr_compile->nstatements;
1302 new->label = $1;
1303 new->body = $3.stmts;
1304
1305 check_labels($1, $3.end_label, $3.end_label_location);
1306 plpgsql_ns_pop();
1307
1308 $$ = (PLpgSQL_stmt *)new;
1309 }
1310 ;
1311
1312 stmt_while : opt_loop_label K_WHILE expr_until_loop loop_body
1313 {
1314 PLpgSQL_stmt_while *new;
1315
1316 new = palloc0(sizeof(PLpgSQL_stmt_while));
1317 new->cmd_type = PLPGSQL_STMT_WHILE;
1318 new->lineno = plpgsql_location_to_lineno(@2);
1319 new->stmtid = ++plpgsql_curr_compile->nstatements;
1320 new->label = $1;
1321 new->cond = $3;
1322 new->body = $4.stmts;
1323
1324 check_labels($1, $4.end_label, $4.end_label_location);
1325 plpgsql_ns_pop();
1326
1327 $$ = (PLpgSQL_stmt *)new;
1328 }
1329 ;
1330
1331 stmt_for : opt_loop_label K_FOR for_control loop_body
1332 {
1333 /* This runs after we've scanned the loop body */
1334 if ($3->cmd_type == PLPGSQL_STMT_FORI)
1335 {
1336 PLpgSQL_stmt_fori *new;
1337
1338 new = (PLpgSQL_stmt_fori *) $3;
1339 new->lineno = plpgsql_location_to_lineno(@2);
1340 new->label = $1;
1341 new->body = $4.stmts;
1342 $$ = (PLpgSQL_stmt *) new;
1343 }
1344 else
1345 {
1346 PLpgSQL_stmt_forq *new;
1347
1348 Assert($3->cmd_type == PLPGSQL_STMT_FORS ||
1349 $3->cmd_type == PLPGSQL_STMT_FORC ||
1350 $3->cmd_type == PLPGSQL_STMT_DYNFORS);
1351 /* forq is the common supertype of all three */
1352 new = (PLpgSQL_stmt_forq *) $3;
1353 new->lineno = plpgsql_location_to_lineno(@2);
1354 new->label = $1;
1355 new->body = $4.stmts;
1356 $$ = (PLpgSQL_stmt *) new;
1357 }
1358
1359 check_labels($1, $4.end_label, $4.end_label_location);
1360 /* close namespace started in opt_loop_label */
1361 plpgsql_ns_pop();
1362 }
1363 ;
1364
1365 for_control : for_variable K_IN
1366 {
1367 int tok = yylex();
1368 int tokloc = yylloc;
1369
1370 if (tok == K_EXECUTE)
1371 {
1372 /* EXECUTE means it's a dynamic FOR loop */
1373 PLpgSQL_stmt_dynfors *new;
1374 PLpgSQL_expr *expr;
1375 int term;
1376
1377 expr = read_sql_expression2(K_LOOP, K_USING,
1378 "LOOP or USING",
1379 &term);
1380
1381 new = palloc0(sizeof(PLpgSQL_stmt_dynfors));
1382 new->cmd_type = PLPGSQL_STMT_DYNFORS;
1383 new->stmtid = ++plpgsql_curr_compile->nstatements;
1384 if ($1.row)
1385 {
1386 new->var = (PLpgSQL_variable *) $1.row;
1387 check_assignable($1.row, @1);
1388 }
1389 else if ($1.scalar)
1390 {
1391 /* convert single scalar to list */
1392 new->var = (PLpgSQL_variable *)
1393 make_scalar_list1($1.name, $1.scalar,
1394 $1.lineno, @1);
1395 /* make_scalar_list1 did check_assignable */
1396 }
1397 else
1398 {
1399 ereport(ERROR,
1400 (errcode(ERRCODE_DATATYPE_MISMATCH),
1401 errmsg("loop variable of loop over rows must be a record variable or list of scalar variables"),
1402 parser_errposition(@1)));
1403 }
1404 new->query = expr;
1405
1406 if (term == K_USING)
1407 {
1408 do
1409 {
1410 expr = read_sql_expression2(',', K_LOOP,
1411 ", or LOOP",
1412 &term);
1413 new->params = lappend(new->params, expr);
1414 } while (term == ',');
1415 }
1416
1417 $$ = (PLpgSQL_stmt *) new;
1418 }
1419 else if (tok == T_DATUM &&
1420 yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_VAR &&
1421 ((PLpgSQL_var *) yylval.wdatum.datum)->datatype->typoid == REFCURSOROID)
1422 {
1423 /* It's FOR var IN cursor */
1424 PLpgSQL_stmt_forc *new;
1425 PLpgSQL_var *cursor = (PLpgSQL_var *) yylval.wdatum.datum;
1426
1427 new = (PLpgSQL_stmt_forc *) palloc0(sizeof(PLpgSQL_stmt_forc));
1428 new->cmd_type = PLPGSQL_STMT_FORC;
1429 new->stmtid = ++plpgsql_curr_compile->nstatements;
1430 new->curvar = cursor->dno;
1431
1432 /* Should have had a single variable name */
1433 if ($1.scalar && $1.row)
1434 ereport(ERROR,
1435 (errcode(ERRCODE_SYNTAX_ERROR),
1436 errmsg("cursor FOR loop must have only one target variable"),
1437 parser_errposition(@1)));
1438
1439 /* can't use an unbound cursor this way */
1440 if (cursor->cursor_explicit_expr == NULL)
1441 ereport(ERROR,
1442 (errcode(ERRCODE_SYNTAX_ERROR),
1443 errmsg("cursor FOR loop must use a bound cursor variable"),
1444 parser_errposition(tokloc)));
1445
1446 /* collect cursor's parameters if any */
1447 new->argquery = read_cursor_args(cursor,
1448 K_LOOP);
1449
1450 /* create loop's private RECORD variable */
1451 new->var = (PLpgSQL_variable *)
1452 plpgsql_build_record($1.name,
1453 $1.lineno,
1454 NULL,
1455 RECORDOID,
1456 true);
1457
1458 $$ = (PLpgSQL_stmt *) new;
1459 }
1460 else
1461 {
1462 PLpgSQL_expr *expr1;
1463 int expr1loc;
1464 bool reverse = false;
1465
1466 /*
1467 * We have to distinguish between two
1468 * alternatives: FOR var IN a .. b and FOR
1469 * var IN query. Unfortunately this is
1470 * tricky, since the query in the second
1471 * form needn't start with a SELECT
1472 * keyword. We use the ugly hack of
1473 * looking for two periods after the first
1474 * token. We also check for the REVERSE
1475 * keyword, which means it must be an
1476 * integer loop.
1477 */
1478 if (tok_is_keyword(tok, &yylval,
1479 K_REVERSE, "reverse"))
1480 reverse = true;
1481 else
1482 plpgsql_push_back_token(tok);
1483
1484 /*
1485 * Read tokens until we see either a ".."
1486 * or a LOOP. The text we read may be either
1487 * an expression or a whole SQL statement, so
1488 * we need to invoke read_sql_construct directly,
1489 * and tell it not to check syntax yet.
1490 */
1491 expr1 = read_sql_construct(DOT_DOT,
1492 K_LOOP,
1493 0,
1494 "LOOP",
1495 RAW_PARSE_DEFAULT,
1496 true,
1497 false,
1498 true,
1499 &expr1loc,
1500 &tok);
1501
1502 if (tok == DOT_DOT)
1503 {
1504 /* Saw "..", so it must be an integer loop */
1505 PLpgSQL_expr *expr2;
1506 PLpgSQL_expr *expr_by;
1507 PLpgSQL_var *fvar;
1508 PLpgSQL_stmt_fori *new;
1509
1510 /*
1511 * Relabel first expression as an expression;
1512 * then we can check its syntax.
1513 */
1514 expr1->parseMode = RAW_PARSE_PLPGSQL_EXPR;
1515 check_sql_expr(expr1->query, expr1->parseMode,
1516 expr1loc);
1517
1518 /* Read and check the second one */
1519 expr2 = read_sql_expression2(K_LOOP, K_BY,
1520 "LOOP",
1521 &tok);
1522
1523 /* Get the BY clause if any */
1524 if (tok == K_BY)
1525 expr_by = read_sql_expression(K_LOOP,
1526 "LOOP");
1527 else
1528 expr_by = NULL;
1529
1530 /* Should have had a single variable name */
1531 if ($1.scalar && $1.row)
1532 ereport(ERROR,
1533 (errcode(ERRCODE_SYNTAX_ERROR),
1534 errmsg("integer FOR loop must have only one target variable"),
1535 parser_errposition(@1)));
1536
1537 /* create loop's private variable */
1538 fvar = (PLpgSQL_var *)
1539 plpgsql_build_variable($1.name,
1540 $1.lineno,
1541 plpgsql_build_datatype(INT4OID,
1542 -1,
1543 InvalidOid,
1544 NULL),
1545 true);
1546
1547 new = palloc0(sizeof(PLpgSQL_stmt_fori));
1548 new->cmd_type = PLPGSQL_STMT_FORI;
1549 new->stmtid = ++plpgsql_curr_compile->nstatements;
1550 new->var = fvar;
1551 new->reverse = reverse;
1552 new->lower = expr1;
1553 new->upper = expr2;
1554 new->step = expr_by;
1555
1556 $$ = (PLpgSQL_stmt *) new;
1557 }
1558 else
1559 {
1560 /*
1561 * No "..", so it must be a query loop.
1562 */
1563 PLpgSQL_stmt_fors *new;
1564
1565 if (reverse)
1566 ereport(ERROR,
1567 (errcode(ERRCODE_SYNTAX_ERROR),
1568 errmsg("cannot specify REVERSE in query FOR loop"),
1569 parser_errposition(tokloc)));
1570
1571 /* Check syntax as a regular query */
1572 check_sql_expr(expr1->query, expr1->parseMode,
1573 expr1loc);
1574
1575 new = palloc0(sizeof(PLpgSQL_stmt_fors));
1576 new->cmd_type = PLPGSQL_STMT_FORS;
1577 new->stmtid = ++plpgsql_curr_compile->nstatements;
1578 if ($1.row)
1579 {
1580 new->var = (PLpgSQL_variable *) $1.row;
1581 check_assignable($1.row, @1);
1582 }
1583 else if ($1.scalar)
1584 {
1585 /* convert single scalar to list */
1586 new->var = (PLpgSQL_variable *)
1587 make_scalar_list1($1.name, $1.scalar,
1588 $1.lineno, @1);
1589 /* make_scalar_list1 did check_assignable */
1590 }
1591 else
1592 {
1593 ereport(ERROR,
1594 (errcode(ERRCODE_SYNTAX_ERROR),
1595 errmsg("loop variable of loop over rows must be a record variable or list of scalar variables"),
1596 parser_errposition(@1)));
1597 }
1598
1599 new->query = expr1;
1600 $$ = (PLpgSQL_stmt *) new;
1601 }
1602 }
1603 }
1604 ;
1605
1606 /*
1607 * Processing the for_variable is tricky because we don't yet know if the
1608 * FOR is an integer FOR loop or a loop over query results. In the former
1609 * case, the variable is just a name that we must instantiate as a loop
1610 * local variable, regardless of any other definition it might have.
1611 * Therefore, we always save the actual identifier into $$.name where it
1612 * can be used for that case. We also save the outer-variable definition,
1613 * if any, because that's what we need for the loop-over-query case. Note
1614 * that we must NOT apply check_assignable() or any other semantic check
1615 * until we know what's what.
1616 *
1617 * However, if we see a comma-separated list of names, we know that it
1618 * can't be an integer FOR loop and so it's OK to check the variables
1619 * immediately. In particular, for T_WORD followed by comma, we should
1620 * complain that the name is not known rather than say it's a syntax error.
1621 * Note that the non-error result of this case sets *both* $$.scalar and
1622 * $$.row; see the for_control production.
1623 */
1624 for_variable : T_DATUM
1625 {
1626 $$.name = NameOfDatum(&($1));
1627 $$.lineno = plpgsql_location_to_lineno(@1);
1628 if ($1.datum->dtype == PLPGSQL_DTYPE_ROW ||
1629 $1.datum->dtype == PLPGSQL_DTYPE_REC)
1630 {
1631 $$.scalar = NULL;
1632 $$.row = $1.datum;
1633 }
1634 else
1635 {
1636 int tok;
1637
1638 $$.scalar = $1.datum;
1639 $$.row = NULL;
1640 /* check for comma-separated list */
1641 tok = yylex();
1642 plpgsql_push_back_token(tok);
1643 if (tok == ',')
1644 $$.row = (PLpgSQL_datum *)
1645 read_into_scalar_list($$.name,
1646 $$.scalar,
1647 @1);
1648 }
1649 }
1650 | T_WORD
1651 {
1652 int tok;
1653
1654 $$.name = $1.ident;
1655 $$.lineno = plpgsql_location_to_lineno(@1);
1656 $$.scalar = NULL;
1657 $$.row = NULL;
1658 /* check for comma-separated list */
1659 tok = yylex();
1660 plpgsql_push_back_token(tok);
1661 if (tok == ',')
1662 word_is_not_variable(&($1), @1);
1663 }
1664 | T_CWORD
1665 {
1666 /* just to give a better message than "syntax error" */
1667 cword_is_not_variable(&($1), @1);
1668 }
1669 ;
1670
1671 stmt_foreach_a : opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRAY expr_until_loop loop_body
1672 {
1673 PLpgSQL_stmt_foreach_a *new;
1674
1675 new = palloc0(sizeof(PLpgSQL_stmt_foreach_a));
1676 new->cmd_type = PLPGSQL_STMT_FOREACH_A;
1677 new->lineno = plpgsql_location_to_lineno(@2);
1678 new->stmtid = ++plpgsql_curr_compile->nstatements;
1679 new->label = $1;
1680 new->slice = $4;
1681 new->expr = $7;
1682 new->body = $8.stmts;
1683
1684 if ($3.row)
1685 {
1686 new->varno = $3.row->dno;
1687 check_assignable($3.row, @3);
1688 }
1689 else if ($3.scalar)
1690 {
1691 new->varno = $3.scalar->dno;
1692 check_assignable($3.scalar, @3);
1693 }
1694 else
1695 {
1696 ereport(ERROR,
1697 (errcode(ERRCODE_SYNTAX_ERROR),
1698 errmsg("loop variable of FOREACH must be a known variable or list of variables"),
1699 parser_errposition(@3)));
1700 }
1701
1702 check_labels($1, $8.end_label, $8.end_label_location);
1703 plpgsql_ns_pop();
1704
1705 $$ = (PLpgSQL_stmt *) new;
1706 }
1707 ;
1708
1709 foreach_slice :
1710 {
1711 $$ = 0;
1712 }
1713 | K_SLICE ICONST
1714 {
1715 $$ = $2;
1716 }
1717 ;
1718
1719 stmt_exit : exit_type opt_label opt_exitcond
1720 {
1721 PLpgSQL_stmt_exit *new;
1722
1723 new = palloc0(sizeof(PLpgSQL_stmt_exit));
1724 new->cmd_type = PLPGSQL_STMT_EXIT;
1725 new->stmtid = ++plpgsql_curr_compile->nstatements;
1726 new->is_exit = $1;
1727 new->lineno = plpgsql_location_to_lineno(@1);
1728 new->label = $2;
1729 new->cond = $3;
1730
1731 if ($2)
1732 {
1733 /* We have a label, so verify it exists */
1734 PLpgSQL_nsitem *label;
1735
1736 label = plpgsql_ns_lookup_label(plpgsql_ns_top(), $2);
1737 if (label == NULL)
1738 ereport(ERROR,
1739 (errcode(ERRCODE_SYNTAX_ERROR),
1740 errmsg("there is no label \"%s\" "
1741 "attached to any block or loop enclosing this statement",
1742 $2),
1743 parser_errposition(@2)));
1744 /* CONTINUE only allows loop labels */
1745 if (label->itemno != PLPGSQL_LABEL_LOOP && !new->is_exit)
1746 ereport(ERROR,
1747 (errcode(ERRCODE_SYNTAX_ERROR),
1748 errmsg("block label \"%s\" cannot be used in CONTINUE",
1749 $2),
1750 parser_errposition(@2)));
1751 }
1752 else
1753 {
1754 /*
1755 * No label, so make sure there is some loop (an
1756 * unlabeled EXIT does not match a block, so this
1757 * is the same test for both EXIT and CONTINUE)
1758 */
1759 if (plpgsql_ns_find_nearest_loop(plpgsql_ns_top()) == NULL)
1760 ereport(ERROR,
1761 (errcode(ERRCODE_SYNTAX_ERROR),
1762 new->is_exit ?
1763 errmsg("EXIT cannot be used outside a loop, unless it has a label") :
1764 errmsg("CONTINUE cannot be used outside a loop"),
1765 parser_errposition(@1)));
1766 }
1767
1768 $$ = (PLpgSQL_stmt *)new;
1769 }
1770 ;
1771
1772 exit_type : K_EXIT
1773 {
1774 $$ = true;
1775 }
1776 | K_CONTINUE
1777 {
1778 $$ = false;
1779 }
1780 ;
1781
1782 stmt_return : K_RETURN
1783 {
1784 int tok;
1785
1786 tok = yylex();
1787 if (tok == 0)
1788 yyerror("unexpected end of function definition");
1789
1790 if (tok_is_keyword(tok, &yylval,
1791 K_NEXT, "next"))
1792 {
1793 $$ = make_return_next_stmt(@1);
1794 }
1795 else if (tok_is_keyword(tok, &yylval,
1796 K_QUERY, "query"))
1797 {
1798 $$ = make_return_query_stmt(@1);
1799 }
1800 else
1801 {
1802 plpgsql_push_back_token(tok);
1803 $$ = make_return_stmt(@1);
1804 }
1805 }
1806 ;
1807
1808 stmt_raise : K_RAISE
1809 {
1810 PLpgSQL_stmt_raise *new;
1811 int tok;
1812
1813 new = palloc(sizeof(PLpgSQL_stmt_raise));
1814
1815 new->cmd_type = PLPGSQL_STMT_RAISE;
1816 new->lineno = plpgsql_location_to_lineno(@1);
1817 new->stmtid = ++plpgsql_curr_compile->nstatements;
1818 new->elog_level = ERROR; /* default */
1819 new->condname = NULL;
1820 new->message = NULL;
1821 new->params = NIL;
1822 new->options = NIL;
1823
1824 tok = yylex();
1825 if (tok == 0)
1826 yyerror("unexpected end of function definition");
1827
1828 /*
1829 * We could have just RAISE, meaning to re-throw
1830 * the current error.
1831 */
1832 if (tok != ';')
1833 {
1834 /*
1835 * First is an optional elog severity level.
1836 */
1837 if (tok_is_keyword(tok, &yylval,
1838 K_EXCEPTION, "exception"))
1839 {
1840 new->elog_level = ERROR;
1841 tok = yylex();
1842 }
1843 else if (tok_is_keyword(tok, &yylval,
1844 K_WARNING, "warning"))
1845 {
1846 new->elog_level = WARNING;
1847 tok = yylex();
1848 }
1849 else if (tok_is_keyword(tok, &yylval,
1850 K_NOTICE, "notice"))
1851 {
1852 new->elog_level = NOTICE;
1853 tok = yylex();
1854 }
1855 else if (tok_is_keyword(tok, &yylval,
1856 K_INFO, "info"))
1857 {
1858 new->elog_level = INFO;
1859 tok = yylex();
1860 }
1861 else if (tok_is_keyword(tok, &yylval,
1862 K_LOG, "log"))
1863 {
1864 new->elog_level = LOG;
1865 tok = yylex();
1866 }
1867 else if (tok_is_keyword(tok, &yylval,
1868 K_DEBUG, "debug"))
1869 {
1870 new->elog_level = DEBUG1;
1871 tok = yylex();
1872 }
1873 if (tok == 0)
1874 yyerror("unexpected end of function definition");
1875
1876 /*
1877 * Next we can have a condition name, or
1878 * equivalently SQLSTATE 'xxxxx', or a string
1879 * literal that is the old-style message format,
1880 * or USING to start the option list immediately.
1881 */
1882 if (tok == SCONST)
1883 {
1884 /* old style message and parameters */
1885 new->message = yylval.str;
1886 /*
1887 * We expect either a semi-colon, which
1888 * indicates no parameters, or a comma that
1889 * begins the list of parameter expressions,
1890 * or USING to begin the options list.
1891 */
1892 tok = yylex();
1893 if (tok != ',' && tok != ';' && tok != K_USING)
1894 yyerror("syntax error");
1895
1896 while (tok == ',')
1897 {
1898 PLpgSQL_expr *expr;
1899
1900 expr = read_sql_construct(',', ';', K_USING,
1901 ", or ; or USING",
1902 RAW_PARSE_PLPGSQL_EXPR,
1903 true, true, true,
1904 NULL, &tok);
1905 new->params = lappend(new->params, expr);
1906 }
1907 }
1908 else if (tok != K_USING)
1909 {
1910 /* must be condition name or SQLSTATE */
1911 if (tok_is_keyword(tok, &yylval,
1912 K_SQLSTATE, "sqlstate"))
1913 {
1914 /* next token should be a string literal */
1915 char *sqlstatestr;
1916
1917 if (yylex() != SCONST)
1918 yyerror("syntax error");
1919 sqlstatestr = yylval.str;
1920
1921 if (strlen(sqlstatestr) != 5)
1922 yyerror("invalid SQLSTATE code");
1923 if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
1924 yyerror("invalid SQLSTATE code");
1925 new->condname = sqlstatestr;
1926 }
1927 else
1928 {
1929 if (tok == T_WORD)
1930 new->condname = yylval.word.ident;
1931 else if (plpgsql_token_is_unreserved_keyword(tok))
1932 new->condname = pstrdup(yylval.keyword);
1933 else
1934 yyerror("syntax error");
1935 plpgsql_recognize_err_condition(new->condname,
1936 false);
1937 }
1938 tok = yylex();
1939 if (tok != ';' && tok != K_USING)
1940 yyerror("syntax error");
1941 }
1942
1943 if (tok == K_USING)
1944 new->options = read_raise_options();
1945 }
1946
1947 check_raise_parameters(new);
1948
1949 $$ = (PLpgSQL_stmt *)new;
1950 }
1951 ;
1952
1953 stmt_assert : K_ASSERT
1954 {
1955 PLpgSQL_stmt_assert *new;
1956 int tok;
1957
1958 new = palloc(sizeof(PLpgSQL_stmt_assert));
1959
1960 new->cmd_type = PLPGSQL_STMT_ASSERT;
1961 new->lineno = plpgsql_location_to_lineno(@1);
1962 new->stmtid = ++plpgsql_curr_compile->nstatements;
1963
1964 new->cond = read_sql_expression2(',', ';',
1965 ", or ;",
1966 &tok);
1967
1968 if (tok == ',')
1969 new->message = read_sql_expression(';', ";");
1970 else
1971 new->message = NULL;
1972
1973 $$ = (PLpgSQL_stmt *) new;
1974 }
1975 ;
1976
1977 loop_body : proc_sect K_END K_LOOP opt_label ';'
1978 {
1979 $$.stmts = $1;
1980 $$.end_label = $4;
1981 $$.end_label_location = @4;
1982 }
1983 ;
1984
1985 /*
1986 * T_WORD+T_CWORD match any initial identifier that is not a known plpgsql
1987 * variable. (The composite case is probably a syntax error, but we'll let
1988 * the core parser decide that.) Normally, we should assume that such a
1989 * word is a SQL statement keyword that isn't also a plpgsql keyword.
1990 * However, if the next token is assignment or '[' or '.', it can't be a valid
1991 * SQL statement, and what we're probably looking at is an intended variable
1992 * assignment. Give an appropriate complaint for that, instead of letting
1993 * the core parser throw an unhelpful "syntax error".
1994 */
1995 stmt_execsql : K_IMPORT
1996 {
1997 $$ = make_execsql_stmt(K_IMPORT, @1);
1998 }
1999 | K_INSERT
2000 {
2001 $$ = make_execsql_stmt(K_INSERT, @1);
2002 }
2003 | T_WORD
2004 {
2005 int tok;
2006
2007 tok = yylex();
2008 plpgsql_push_back_token(tok);
2009 if (tok == '=' || tok == COLON_EQUALS ||
2010 tok == '[' || tok == '.')
2011 word_is_not_variable(&($1), @1);
2012 $$ = make_execsql_stmt(T_WORD, @1);
2013 }
2014 | T_CWORD
2015 {
2016 int tok;
2017
2018 tok = yylex();
2019 plpgsql_push_back_token(tok);
2020 if (tok == '=' || tok == COLON_EQUALS ||
2021 tok == '[' || tok == '.')
2022 cword_is_not_variable(&($1), @1);
2023 $$ = make_execsql_stmt(T_CWORD, @1);
2024 }
2025 ;
2026
2027 stmt_dynexecute : K_EXECUTE
2028 {
2029 PLpgSQL_stmt_dynexecute *new;
2030 PLpgSQL_expr *expr;
2031 int endtoken;
2032
2033 expr = read_sql_construct(K_INTO, K_USING, ';',
2034 "INTO or USING or ;",
2035 RAW_PARSE_PLPGSQL_EXPR,
2036 true, true, true,
2037 NULL, &endtoken);
2038
2039 new = palloc(sizeof(PLpgSQL_stmt_dynexecute));
2040 new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
2041 new->lineno = plpgsql_location_to_lineno(@1);
2042 new->stmtid = ++plpgsql_curr_compile->nstatements;
2043 new->query = expr;
2044 new->into = false;
2045 new->strict = false;
2046 new->target = NULL;
2047 new->params = NIL;
2048
2049 /*
2050 * We loop to allow the INTO and USING clauses to
2051 * appear in either order, since people easily get
2052 * that wrong. This coding also prevents "INTO foo"
2053 * from getting absorbed into a USING expression,
2054 * which is *really* confusing.
2055 */
2056 for (;;)
2057 {
2058 if (endtoken == K_INTO)
2059 {
2060 if (new->into) /* multiple INTO */
2061 yyerror("syntax error");
2062 new->into = true;
2063 read_into_target(&new->target, &new->strict);
2064 endtoken = yylex();
2065 }
2066 else if (endtoken == K_USING)
2067 {
2068 if (new->params) /* multiple USING */
2069 yyerror("syntax error");
2070 do
2071 {
2072 expr = read_sql_construct(',', ';', K_INTO,
2073 ", or ; or INTO",
2074 RAW_PARSE_PLPGSQL_EXPR,
2075 true, true, true,
2076 NULL, &endtoken);
2077 new->params = lappend(new->params, expr);
2078 } while (endtoken == ',');
2079 }
2080 else if (endtoken == ';')
2081 break;
2082 else
2083 yyerror("syntax error");
2084 }
2085
2086 $$ = (PLpgSQL_stmt *)new;
2087 }
2088 ;
2089
2090
2091 stmt_open : K_OPEN cursor_variable
2092 {
2093 PLpgSQL_stmt_open *new;
2094 int tok;
2095
2096 new = palloc0(sizeof(PLpgSQL_stmt_open));
2097 new->cmd_type = PLPGSQL_STMT_OPEN;
2098 new->lineno = plpgsql_location_to_lineno(@1);
2099 new->stmtid = ++plpgsql_curr_compile->nstatements;
2100 new->curvar = $2->dno;
2101 new->cursor_options = CURSOR_OPT_FAST_PLAN;
2102
2103 if ($2->cursor_explicit_expr == NULL)
2104 {
2105 /* be nice if we could use opt_scrollable here */
2106 tok = yylex();
2107 if (tok_is_keyword(tok, &yylval,
2108 K_NO, "no"))
2109 {
2110 tok = yylex();
2111 if (tok_is_keyword(tok, &yylval,
2112 K_SCROLL, "scroll"))
2113 {
2114 new->cursor_options |= CURSOR_OPT_NO_SCROLL;
2115 tok = yylex();
2116 }
2117 }
2118 else if (tok_is_keyword(tok, &yylval,
2119 K_SCROLL, "scroll"))
2120 {
2121 new->cursor_options |= CURSOR_OPT_SCROLL;
2122 tok = yylex();
2123 }
2124
2125 if (tok != K_FOR)
2126 yyerror("syntax error, expected \"FOR\"");
2127
2128 tok = yylex();
2129 if (tok == K_EXECUTE)
2130 {
2131 int endtoken;
2132
2133 new->dynquery =
2134 read_sql_expression2(K_USING, ';',
2135 "USING or ;",
2136 &endtoken);
2137
2138 /* If we found "USING", collect argument(s) */
2139 if (endtoken == K_USING)
2140 {
2141 PLpgSQL_expr *expr;
2142
2143 do
2144 {
2145 expr = read_sql_expression2(',', ';',
2146 ", or ;",
2147 &endtoken);
2148 new->params = lappend(new->params,
2149 expr);
2150 } while (endtoken == ',');
2151 }
2152 }
2153 else
2154 {
2155 plpgsql_push_back_token(tok);
2156 new->query = read_sql_stmt();
2157 }
2158 }
2159 else
2160 {
2161 /* predefined cursor query, so read args */
2162 new->argquery = read_cursor_args($2, ';');
2163 }
2164
2165 $$ = (PLpgSQL_stmt *)new;
2166 }
2167 ;
2168
2169 stmt_fetch : K_FETCH opt_fetch_direction cursor_variable K_INTO
2170 {
2171 PLpgSQL_stmt_fetch *fetch = $2;
2172 PLpgSQL_variable *target;
2173
2174 /* We have already parsed everything through the INTO keyword */
2175 read_into_target(&target, NULL);
2176
2177 if (yylex() != ';')
2178 yyerror("syntax error");
2179
2180 /*
2181 * We don't allow multiple rows in PL/pgSQL's FETCH
2182 * statement, only in MOVE.
2183 */
2184 if (fetch->returns_multiple_rows)
2185 ereport(ERROR,
2186 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2187 errmsg("FETCH statement cannot return multiple rows"),
2188 parser_errposition(@1)));
2189
2190 fetch->lineno = plpgsql_location_to_lineno(@1);
2191 fetch->target = target;
2192 fetch->curvar = $3->dno;
2193 fetch->is_move = false;
2194
2195 $$ = (PLpgSQL_stmt *)fetch;
2196 }
2197 ;
2198
2199 stmt_move : K_MOVE opt_fetch_direction cursor_variable ';'
2200 {
2201 PLpgSQL_stmt_fetch *fetch = $2;
2202
2203 fetch->lineno = plpgsql_location_to_lineno(@1);
2204 fetch->curvar = $3->dno;
2205 fetch->is_move = true;
2206
2207 $$ = (PLpgSQL_stmt *)fetch;
2208 }
2209 ;
2210
2211 opt_fetch_direction :
2212 {
2213 $$ = read_fetch_direction();
2214 }
2215 ;
2216
2217 stmt_close : K_CLOSE cursor_variable ';'
2218 {
2219 PLpgSQL_stmt_close *new;
2220
2221 new = palloc(sizeof(PLpgSQL_stmt_close));
2222 new->cmd_type = PLPGSQL_STMT_CLOSE;
2223 new->lineno = plpgsql_location_to_lineno(@1);
2224 new->stmtid = ++plpgsql_curr_compile->nstatements;
2225 new->curvar = $2->dno;
2226
2227 $$ = (PLpgSQL_stmt *)new;
2228 }
2229 ;
2230
2231 stmt_null : K_NULL ';'
2232 {
2233 /* We do not bother building a node for NULL */
2234 $$ = NULL;
2235 }
2236 ;
2237
2238 stmt_commit : K_COMMIT opt_transaction_chain ';'
2239 {
2240 PLpgSQL_stmt_commit *new;
2241
2242 new = palloc(sizeof(PLpgSQL_stmt_commit));
2243 new->cmd_type = PLPGSQL_STMT_COMMIT;
2244 new->lineno = plpgsql_location_to_lineno(@1);
2245 new->stmtid = ++plpgsql_curr_compile->nstatements;
2246 new->chain = $2;
2247
2248 $$ = (PLpgSQL_stmt *)new;
2249 }
2250 ;
2251
2252 stmt_rollback : K_ROLLBACK opt_transaction_chain ';'
2253 {
2254 PLpgSQL_stmt_rollback *new;
2255
2256 new = palloc(sizeof(PLpgSQL_stmt_rollback));
2257 new->cmd_type = PLPGSQL_STMT_ROLLBACK;
2258 new->lineno = plpgsql_location_to_lineno(@1);
2259 new->stmtid = ++plpgsql_curr_compile->nstatements;
2260 new->chain = $2;
2261
2262 $$ = (PLpgSQL_stmt *)new;
2263 }
2264 ;
2265
2266 opt_transaction_chain:
2267 K_AND K_CHAIN { $$ = true; }
2268 | K_AND K_NO K_CHAIN { $$ = false; }
2269 | /* EMPTY */ { $$ = false; }
2270 ;
2271
2272
2273 cursor_variable : T_DATUM
2274 {
2275 /*
2276 * In principle we should support a cursor_variable
2277 * that is an array element, but for now we don't, so
2278 * just throw an error if next token is '['.
2279 */
2280 if ($1.datum->dtype != PLPGSQL_DTYPE_VAR ||
2281 plpgsql_peek() == '[')
2282 ereport(ERROR,
2283 (errcode(ERRCODE_DATATYPE_MISMATCH),
2284 errmsg("cursor variable must be a simple variable"),
2285 parser_errposition(@1)));
2286
2287 if (((PLpgSQL_var *) $1.datum)->datatype->typoid != REFCURSOROID)
2288 ereport(ERROR,
2289 (errcode(ERRCODE_DATATYPE_MISMATCH),
2290 errmsg("variable \"%s\" must be of type cursor or refcursor",
2291 ((PLpgSQL_var *) $1.datum)->refname),
2292 parser_errposition(@1)));
2293 $$ = (PLpgSQL_var *) $1.datum;
2294 }
2295 | T_WORD
2296 {
2297 /* just to give a better message than "syntax error" */
2298 word_is_not_variable(&($1), @1);
2299 }
2300 | T_CWORD
2301 {
2302 /* just to give a better message than "syntax error" */
2303 cword_is_not_variable(&($1), @1);
2304 }
2305 ;
2306
2307 exception_sect :
2308 { $$ = NULL; }
2309 | K_EXCEPTION
2310 {
2311 /*
2312 * We use a mid-rule action to add these
2313 * special variables to the namespace before
2314 * parsing the WHEN clauses themselves. The
2315 * scope of the names extends to the end of the
2316 * current block.
2317 */
2318 int lineno = plpgsql_location_to_lineno(@1);
2319 PLpgSQL_exception_block *new = palloc(sizeof(PLpgSQL_exception_block));
2320 PLpgSQL_variable *var;
2321
2322 var = plpgsql_build_variable("sqlstate", lineno,
2323 plpgsql_build_datatype(TEXTOID,
2324 -1,
2325 plpgsql_curr_compile->fn_input_collation,
2326 NULL),
2327 true);
2328 var->isconst = true;
2329 new->sqlstate_varno = var->dno;
2330
2331 var = plpgsql_build_variable("sqlerrm", lineno,
2332 plpgsql_build_datatype(TEXTOID,
2333 -1,
2334 plpgsql_curr_compile->fn_input_collation,
2335 NULL),
2336 true);
2337 var->isconst = true;
2338 new->sqlerrm_varno = var->dno;
2339
2340 $<exception_block>$ = new;
2341 }
2342 proc_exceptions
2343 {
2344 PLpgSQL_exception_block *new = $<exception_block>2;
2345 new->exc_list = $3;
2346
2347 $$ = new;
2348 }
2349 ;
2350
2351 proc_exceptions : proc_exceptions proc_exception
2352 {
2353 $$ = lappend($1, $2);
2354 }
2355 | proc_exception
2356 {
2357 $$ = list_make1($1);
2358 }
2359 ;
2360
2361 proc_exception : K_WHEN proc_conditions K_THEN proc_sect
2362 {
2363 PLpgSQL_exception *new;
2364
2365 new = palloc0(sizeof(PLpgSQL_exception));
2366 new->lineno = plpgsql_location_to_lineno(@1);
2367 new->conditions = $2;
2368 new->action = $4;
2369
2370 $$ = new;
2371 }
2372 ;
2373
2374 proc_conditions : proc_conditions K_OR proc_condition
2375 {
2376 PLpgSQL_condition *old;
2377
2378 for (old = $1; old->next != NULL; old = old->next)
2379 /* skip */ ;
2380 old->next = $3;
2381 $$ = $1;
2382 }
2383 | proc_condition
2384 {
2385 $$ = $1;
2386 }
2387 ;
2388
2389 proc_condition : any_identifier
2390 {
2391 if (strcmp($1, "sqlstate") != 0)
2392 {
2393 $$ = plpgsql_parse_err_condition($1);
2394 }
2395 else
2396 {
2397 PLpgSQL_condition *new;
2398 char *sqlstatestr;
2399
2400 /* next token should be a string literal */
2401 if (yylex() != SCONST)
2402 yyerror("syntax error");
2403 sqlstatestr = yylval.str;
2404
2405 if (strlen(sqlstatestr) != 5)
2406 yyerror("invalid SQLSTATE code");
2407 if (strspn(sqlstatestr, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") != 5)
2408 yyerror("invalid SQLSTATE code");
2409
2410 new = palloc(sizeof(PLpgSQL_condition));
2411 new->sqlerrstate =
2412 MAKE_SQLSTATE(sqlstatestr[0],
2413 sqlstatestr[1],
2414 sqlstatestr[2],
2415 sqlstatestr[3],
2416 sqlstatestr[4]);
2417 new->condname = sqlstatestr;
2418 new->next = NULL;
2419
2420 $$ = new;
2421 }
2422 }
2423 ;
2424
2425 expr_until_semi :
2426 { $$ = read_sql_expression(';', ";"); }
2427 ;
2428
2429 expr_until_then :
2430 { $$ = read_sql_expression(K_THEN, "THEN"); }
2431 ;
2432
2433 expr_until_loop :
2434 { $$ = read_sql_expression(K_LOOP, "LOOP"); }
2435 ;
2436
2437 opt_block_label :
2438 {
2439 plpgsql_ns_push(NULL, PLPGSQL_LABEL_BLOCK);
2440 $$ = NULL;
2441 }
2442 | LESS_LESS any_identifier GREATER_GREATER
2443 {
2444 plpgsql_ns_push($2, PLPGSQL_LABEL_BLOCK);
2445 $$ = $2;
2446 }
2447 ;
2448
2449 opt_loop_label :
2450 {
2451 plpgsql_ns_push(NULL, PLPGSQL_LABEL_LOOP);
2452 $$ = NULL;
2453 }
2454 | LESS_LESS any_identifier GREATER_GREATER
2455 {
2456 plpgsql_ns_push($2, PLPGSQL_LABEL_LOOP);
2457 $$ = $2;
2458 }
2459 ;
2460
2461 opt_label :
2462 {
2463 $$ = NULL;
2464 }
2465 | any_identifier
2466 {
2467 /* label validity will be checked by outer production */
2468 $$ = $1;
2469 }
2470 ;
2471
2472 opt_exitcond : ';'
2473 { $$ = NULL; }
2474 | K_WHEN expr_until_semi
2475 { $$ = $2; }
2476 ;
2477
2478 /*
2479 * need to allow DATUM because scanner will have tried to resolve as variable
2480 */
2481 any_identifier : T_WORD
2482 {
2483 $$ = $1.ident;
2484 }
2485 | unreserved_keyword
2486 {
2487 $$ = pstrdup($1);
2488 }
2489 | T_DATUM
2490 {
2491 if ($1.ident == NULL) /* composite name not OK */
2492 yyerror("syntax error");
2493 $$ = $1.ident;
2494 }
2495 ;
2496
2497 unreserved_keyword :
2498 K_ABSOLUTE
2499 | K_ALIAS
2500 | K_AND
2501 | K_ARRAY
2502 | K_ASSERT
2503 | K_BACKWARD
2504 | K_CALL
2505 | K_CHAIN
2506 | K_CLOSE
2507 | K_COLLATE
2508 | K_COLUMN
2509 | K_COLUMN_NAME
2510 | K_COMMIT
2511 | K_CONSTANT
2512 | K_CONSTRAINT
2513 | K_CONSTRAINT_NAME
2514 | K_CONTINUE
2515 | K_CURRENT
2516 | K_CURSOR
2517 | K_DATATYPE
2518 | K_DEBUG
2519 | K_DEFAULT
2520 | K_DETAIL
2521 | K_DIAGNOSTICS
2522 | K_DO
2523 | K_DUMP
2524 | K_ELSIF
2525 | K_ERRCODE
2526 | K_ERROR
2527 | K_EXCEPTION
2528 | K_EXIT
2529 | K_FETCH
2530 | K_FIRST
2531 | K_FORWARD
2532 | K_GET
2533 | K_HINT
2534 | K_IMPORT
2535 | K_INFO
2536 | K_INSERT
2537 | K_IS
2538 | K_LAST
2539 | K_LOG
2540 | K_MESSAGE
2541 | K_MESSAGE_TEXT
2542 | K_MOVE
2543 | K_NEXT
2544 | K_NO
2545 | K_NOTICE
2546 | K_OPEN
2547 | K_OPTION
2548 | K_PERFORM
2549 | K_PG_CONTEXT
2550 | K_PG_DATATYPE_NAME
2551 | K_PG_EXCEPTION_CONTEXT
2552 | K_PG_EXCEPTION_DETAIL
2553 | K_PG_EXCEPTION_HINT
2554 | K_PRINT_STRICT_PARAMS
2555 | K_PRIOR
2556 | K_QUERY
2557 | K_RAISE
2558 | K_RELATIVE
2559 | K_RETURN
2560 | K_RETURNED_SQLSTATE
2561 | K_REVERSE
2562 | K_ROLLBACK
2563 | K_ROW_COUNT
2564 | K_ROWTYPE
2565 | K_SCHEMA
2566 | K_SCHEMA_NAME
2567 | K_SCROLL
2568 | K_SLICE
2569 | K_SQLSTATE
2570 | K_STACKED
2571 | K_TABLE
2572 | K_TABLE_NAME
2573 | K_TYPE
2574 | K_USE_COLUMN
2575 | K_USE_VARIABLE
2576 | K_VARIABLE_CONFLICT
2577 | K_WARNING
2578 ;
2579
2580 %%
2581
2582 /*
2583 * Check whether a token represents an "unreserved keyword".
2584 * We have various places where we want to recognize a keyword in preference
2585 * to a variable name, but not reserve that keyword in other contexts.
2586 * Hence, this kluge.
2587 */
2588 static bool
2589 tok_is_keyword(int token, union YYSTYPE *lval,
2590 int kw_token, const char *kw_str)
2591 {
2592 if (token == kw_token)
2593 {
2594 /* Normal case, was recognized by scanner (no conflicting variable) */
2595 return true;
2596 }
2597 else if (token == T_DATUM)
2598 {
2599 /*
2600 * It's a variable, so recheck the string name. Note we will not
2601 * match composite names (hence an unreserved word followed by "."
2602 * will not be recognized).
2603 */
2604 if (!lval->wdatum.quoted && lval->wdatum.ident != NULL &&
2605 strcmp(lval->wdatum.ident, kw_str) == 0)
2606 return true;
2607 }
2608 return false; /* not the keyword */
2609 }
2610
2611 /*
2612 * Convenience routine to complain when we expected T_DATUM and got T_WORD,
2613 * ie, unrecognized variable.
2614 */
2615 static void
word_is_not_variable(PLword * word,int location)2616 word_is_not_variable(PLword *word, int location)
2617 {
2618 ereport(ERROR,
2619 (errcode(ERRCODE_SYNTAX_ERROR),
2620 errmsg("\"%s\" is not a known variable",
2621 word->ident),
2622 parser_errposition(location)));
2623 }
2624
2625 /* Same, for a CWORD */
2626 static void
cword_is_not_variable(PLcword * cword,int location)2627 cword_is_not_variable(PLcword *cword, int location)
2628 {
2629 ereport(ERROR,
2630 (errcode(ERRCODE_SYNTAX_ERROR),
2631 errmsg("\"%s\" is not a known variable",
2632 NameListToString(cword->idents)),
2633 parser_errposition(location)));
2634 }
2635
2636 /*
2637 * Convenience routine to complain when we expected T_DATUM and got
2638 * something else. "tok" must be the current token, since we also
2639 * look at yylval and yylloc.
2640 */
2641 static void
current_token_is_not_variable(int tok)2642 current_token_is_not_variable(int tok)
2643 {
2644 if (tok == T_WORD)
2645 word_is_not_variable(&(yylval.word), yylloc);
2646 else if (tok == T_CWORD)
2647 cword_is_not_variable(&(yylval.cword), yylloc);
2648 else
2649 yyerror("syntax error");
2650 }
2651
2652 /* Convenience routine to read an expression with one possible terminator */
2653 static PLpgSQL_expr *
read_sql_expression(int until,const char * expected)2654 read_sql_expression(int until, const char *expected)
2655 {
2656 return read_sql_construct(until, 0, 0, expected,
2657 RAW_PARSE_PLPGSQL_EXPR,
2658 true, true, true, NULL, NULL);
2659 }
2660
2661 /* Convenience routine to read an expression with two possible terminators */
2662 static PLpgSQL_expr *
read_sql_expression2(int until,int until2,const char * expected,int * endtoken)2663 read_sql_expression2(int until, int until2, const char *expected,
2664 int *endtoken)
2665 {
2666 return read_sql_construct(until, until2, 0, expected,
2667 RAW_PARSE_PLPGSQL_EXPR,
2668 true, true, true, NULL, endtoken);
2669 }
2670
2671 /* Convenience routine to read a SQL statement that must end with ';' */
2672 static PLpgSQL_expr *
read_sql_stmt(void)2673 read_sql_stmt(void)
2674 {
2675 return read_sql_construct(';', 0, 0, ";",
2676 RAW_PARSE_DEFAULT,
2677 false, true, true, NULL, NULL);
2678 }
2679
2680 /*
2681 * Read a SQL construct and build a PLpgSQL_expr for it.
2682 *
2683 * until: token code for expected terminator
2684 * until2: token code for alternate terminator (pass 0 if none)
2685 * until3: token code for another alternate terminator (pass 0 if none)
2686 * expected: text to use in complaining that terminator was not found
2687 * parsemode: raw_parser() mode to use
2688 * isexpression: whether to say we're reading an "expression" or a "statement"
2689 * valid_sql: whether to check the syntax of the expr
2690 * trim: trim trailing whitespace
2691 * startloc: if not NULL, location of first token is stored at *startloc
2692 * endtoken: if not NULL, ending token is stored at *endtoken
2693 * (this is only interesting if until2 or until3 isn't zero)
2694 */
2695 static PLpgSQL_expr *
read_sql_construct(int until,int until2,int until3,const char * expected,RawParseMode parsemode,bool isexpression,bool valid_sql,bool trim,int * startloc,int * endtoken)2696 read_sql_construct(int until,
2697 int until2,
2698 int until3,
2699 const char *expected,
2700 RawParseMode parsemode,
2701 bool isexpression,
2702 bool valid_sql,
2703 bool trim,
2704 int *startloc,
2705 int *endtoken)
2706 {
2707 int tok;
2708 StringInfoData ds;
2709 IdentifierLookup save_IdentifierLookup;
2710 int startlocation = -1;
2711 int parenlevel = 0;
2712 PLpgSQL_expr *expr;
2713
2714 initStringInfo(&ds);
2715
2716 /* special lookup mode for identifiers within the SQL text */
2717 save_IdentifierLookup = plpgsql_IdentifierLookup;
2718 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR;
2719
2720 for (;;)
2721 {
2722 tok = yylex();
2723 if (startlocation < 0) /* remember loc of first token */
2724 startlocation = yylloc;
2725 if (tok == until && parenlevel == 0)
2726 break;
2727 if (tok == until2 && parenlevel == 0)
2728 break;
2729 if (tok == until3 && parenlevel == 0)
2730 break;
2731 if (tok == '(' || tok == '[')
2732 parenlevel++;
2733 else if (tok == ')' || tok == ']')
2734 {
2735 parenlevel--;
2736 if (parenlevel < 0)
2737 yyerror("mismatched parentheses");
2738 }
2739 /*
2740 * End of function definition is an error, and we don't expect to
2741 * hit a semicolon either (unless it's the until symbol, in which
2742 * case we should have fallen out above).
2743 */
2744 if (tok == 0 || tok == ';')
2745 {
2746 if (parenlevel != 0)
2747 yyerror("mismatched parentheses");
2748 if (isexpression)
2749 ereport(ERROR,
2750 (errcode(ERRCODE_SYNTAX_ERROR),
2751 errmsg("missing \"%s\" at end of SQL expression",
2752 expected),
2753 parser_errposition(yylloc)));
2754 else
2755 ereport(ERROR,
2756 (errcode(ERRCODE_SYNTAX_ERROR),
2757 errmsg("missing \"%s\" at end of SQL statement",
2758 expected),
2759 parser_errposition(yylloc)));
2760 }
2761 }
2762
2763 plpgsql_IdentifierLookup = save_IdentifierLookup;
2764
2765 if (startloc)
2766 *startloc = startlocation;
2767 if (endtoken)
2768 *endtoken = tok;
2769
2770 /* give helpful complaint about empty input */
2771 if (startlocation >= yylloc)
2772 {
2773 if (isexpression)
2774 yyerror("missing expression");
2775 else
2776 yyerror("missing SQL statement");
2777 }
2778
2779 plpgsql_append_source_text(&ds, startlocation, yylloc);
2780
2781 /* trim any trailing whitespace, for neatness */
2782 if (trim)
2783 {
2784 while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]))
2785 ds.data[--ds.len] = '\0';
2786 }
2787
2788 expr = palloc0(sizeof(PLpgSQL_expr));
2789 expr->query = pstrdup(ds.data);
2790 expr->parseMode = parsemode;
2791 expr->plan = NULL;
2792 expr->paramnos = NULL;
2793 expr->target_param = -1;
2794 expr->ns = plpgsql_ns_top();
2795 pfree(ds.data);
2796
2797 if (valid_sql)
2798 check_sql_expr(expr->query, expr->parseMode, startlocation);
2799
2800 return expr;
2801 }
2802
2803 static PLpgSQL_type *
read_datatype(int tok)2804 read_datatype(int tok)
2805 {
2806 StringInfoData ds;
2807 char *type_name;
2808 int startlocation;
2809 PLpgSQL_type *result;
2810 int parenlevel = 0;
2811
2812 /* Should only be called while parsing DECLARE sections */
2813 Assert(plpgsql_IdentifierLookup == IDENTIFIER_LOOKUP_DECLARE);
2814
2815 /* Often there will be a lookahead token, but if not, get one */
2816 if (tok == YYEMPTY)
2817 tok = yylex();
2818
2819 startlocation = yylloc;
2820
2821 /*
2822 * If we have a simple or composite identifier, check for %TYPE
2823 * and %ROWTYPE constructs.
2824 */
2825 if (tok == T_WORD)
2826 {
2827 char *dtname = yylval.word.ident;
2828
2829 tok = yylex();
2830 if (tok == '%')
2831 {
2832 tok = yylex();
2833 if (tok_is_keyword(tok, &yylval,
2834 K_TYPE, "type"))
2835 {
2836 result = plpgsql_parse_wordtype(dtname);
2837 if (result)
2838 return result;
2839 }
2840 else if (tok_is_keyword(tok, &yylval,
2841 K_ROWTYPE, "rowtype"))
2842 {
2843 result = plpgsql_parse_wordrowtype(dtname);
2844 if (result)
2845 return result;
2846 }
2847 }
2848 }
2849 else if (plpgsql_token_is_unreserved_keyword(tok))
2850 {
2851 char *dtname = pstrdup(yylval.keyword);
2852
2853 tok = yylex();
2854 if (tok == '%')
2855 {
2856 tok = yylex();
2857 if (tok_is_keyword(tok, &yylval,
2858 K_TYPE, "type"))
2859 {
2860 result = plpgsql_parse_wordtype(dtname);
2861 if (result)
2862 return result;
2863 }
2864 else if (tok_is_keyword(tok, &yylval,
2865 K_ROWTYPE, "rowtype"))
2866 {
2867 result = plpgsql_parse_wordrowtype(dtname);
2868 if (result)
2869 return result;
2870 }
2871 }
2872 }
2873 else if (tok == T_CWORD)
2874 {
2875 List *dtnames = yylval.cword.idents;
2876
2877 tok = yylex();
2878 if (tok == '%')
2879 {
2880 tok = yylex();
2881 if (tok_is_keyword(tok, &yylval,
2882 K_TYPE, "type"))
2883 {
2884 result = plpgsql_parse_cwordtype(dtnames);
2885 if (result)
2886 return result;
2887 }
2888 else if (tok_is_keyword(tok, &yylval,
2889 K_ROWTYPE, "rowtype"))
2890 {
2891 result = plpgsql_parse_cwordrowtype(dtnames);
2892 if (result)
2893 return result;
2894 }
2895 }
2896 }
2897
2898 while (tok != ';')
2899 {
2900 if (tok == 0)
2901 {
2902 if (parenlevel != 0)
2903 yyerror("mismatched parentheses");
2904 else
2905 yyerror("incomplete data type declaration");
2906 }
2907 /* Possible followers for datatype in a declaration */
2908 if (tok == K_COLLATE || tok == K_NOT ||
2909 tok == '=' || tok == COLON_EQUALS || tok == K_DEFAULT)
2910 break;
2911 /* Possible followers for datatype in a cursor_arg list */
2912 if ((tok == ',' || tok == ')') && parenlevel == 0)
2913 break;
2914 if (tok == '(')
2915 parenlevel++;
2916 else if (tok == ')')
2917 parenlevel--;
2918
2919 tok = yylex();
2920 }
2921
2922 /* set up ds to contain complete typename text */
2923 initStringInfo(&ds);
2924 plpgsql_append_source_text(&ds, startlocation, yylloc);
2925 type_name = ds.data;
2926
2927 if (type_name[0] == '\0')
2928 yyerror("missing data type declaration");
2929
2930 result = parse_datatype(type_name, startlocation);
2931
2932 pfree(ds.data);
2933
2934 plpgsql_push_back_token(tok);
2935
2936 return result;
2937 }
2938
2939 static PLpgSQL_stmt *
make_execsql_stmt(int firsttoken,int location)2940 make_execsql_stmt(int firsttoken, int location)
2941 {
2942 StringInfoData ds;
2943 IdentifierLookup save_IdentifierLookup;
2944 PLpgSQL_stmt_execsql *execsql;
2945 PLpgSQL_expr *expr;
2946 PLpgSQL_variable *target = NULL;
2947 int tok;
2948 int prev_tok;
2949 bool have_into = false;
2950 bool have_strict = false;
2951 int into_start_loc = -1;
2952 int into_end_loc = -1;
2953
2954 initStringInfo(&ds);
2955
2956 /* special lookup mode for identifiers within the SQL text */
2957 save_IdentifierLookup = plpgsql_IdentifierLookup;
2958 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR;
2959
2960 /*
2961 * Scan to the end of the SQL command. Identify any INTO-variables
2962 * clause lurking within it, and parse that via read_into_target().
2963 *
2964 * Because INTO is sometimes used in the main SQL grammar, we have to be
2965 * careful not to take any such usage of INTO as a PL/pgSQL INTO clause.
2966 * There are currently three such cases:
2967 *
2968 * 1. SELECT ... INTO. We don't care, we just override that with the
2969 * PL/pgSQL definition.
2970 *
2971 * 2. INSERT INTO. This is relatively easy to recognize since the words
2972 * must appear adjacently; but we can't assume INSERT starts the command,
2973 * because it can appear in CREATE RULE or WITH. Unfortunately, INSERT is
2974 * *not* fully reserved, so that means there is a chance of a false match;
2975 * but it's not very likely.
2976 *
2977 * 3. IMPORT FOREIGN SCHEMA ... INTO. This is not allowed in CREATE RULE
2978 * or WITH, so we just check for IMPORT as the command's first token.
2979 * (If IMPORT FOREIGN SCHEMA returned data someone might wish to capture
2980 * with an INTO-variables clause, we'd have to work much harder here.)
2981 *
2982 * Fortunately, INTO is a fully reserved word in the main grammar, so
2983 * at least we need not worry about it appearing as an identifier.
2984 *
2985 * Any future additional uses of INTO in the main grammar will doubtless
2986 * break this logic again ... beware!
2987 */
2988 tok = firsttoken;
2989 for (;;)
2990 {
2991 prev_tok = tok;
2992 tok = yylex();
2993 if (have_into && into_end_loc < 0)
2994 into_end_loc = yylloc; /* token after the INTO part */
2995 if (tok == ';')
2996 break;
2997 if (tok == 0)
2998 yyerror("unexpected end of function definition");
2999 if (tok == K_INTO)
3000 {
3001 if (prev_tok == K_INSERT)
3002 continue; /* INSERT INTO is not an INTO-target */
3003 if (firsttoken == K_IMPORT)
3004 continue; /* IMPORT ... INTO is not an INTO-target */
3005 if (have_into)
3006 yyerror("INTO specified more than once");
3007 have_into = true;
3008 into_start_loc = yylloc;
3009 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
3010 read_into_target(&target, &have_strict);
3011 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR;
3012 }
3013 }
3014
3015 plpgsql_IdentifierLookup = save_IdentifierLookup;
3016
3017 if (have_into)
3018 {
3019 /*
3020 * Insert an appropriate number of spaces corresponding to the
3021 * INTO text, so that locations within the redacted SQL statement
3022 * still line up with those in the original source text.
3023 */
3024 plpgsql_append_source_text(&ds, location, into_start_loc);
3025 appendStringInfoSpaces(&ds, into_end_loc - into_start_loc);
3026 plpgsql_append_source_text(&ds, into_end_loc, yylloc);
3027 }
3028 else
3029 plpgsql_append_source_text(&ds, location, yylloc);
3030
3031 /* trim any trailing whitespace, for neatness */
3032 while (ds.len > 0 && scanner_isspace(ds.data[ds.len - 1]))
3033 ds.data[--ds.len] = '\0';
3034
3035 expr = palloc0(sizeof(PLpgSQL_expr));
3036 expr->query = pstrdup(ds.data);
3037 expr->parseMode = RAW_PARSE_DEFAULT;
3038 expr->plan = NULL;
3039 expr->paramnos = NULL;
3040 expr->target_param = -1;
3041 expr->ns = plpgsql_ns_top();
3042 pfree(ds.data);
3043
3044 check_sql_expr(expr->query, expr->parseMode, location);
3045
3046 execsql = palloc0(sizeof(PLpgSQL_stmt_execsql));
3047 execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
3048 execsql->lineno = plpgsql_location_to_lineno(location);
3049 execsql->stmtid = ++plpgsql_curr_compile->nstatements;
3050 execsql->sqlstmt = expr;
3051 execsql->into = have_into;
3052 execsql->strict = have_strict;
3053 execsql->target = target;
3054
3055 return (PLpgSQL_stmt *) execsql;
3056 }
3057
3058
3059 /*
3060 * Read FETCH or MOVE direction clause (everything through FROM/IN).
3061 */
3062 static PLpgSQL_stmt_fetch *
read_fetch_direction(void)3063 read_fetch_direction(void)
3064 {
3065 PLpgSQL_stmt_fetch *fetch;
3066 int tok;
3067 bool check_FROM = true;
3068
3069 /*
3070 * We create the PLpgSQL_stmt_fetch struct here, but only fill in
3071 * the fields arising from the optional direction clause
3072 */
3073 fetch = (PLpgSQL_stmt_fetch *) palloc0(sizeof(PLpgSQL_stmt_fetch));
3074 fetch->cmd_type = PLPGSQL_STMT_FETCH;
3075 fetch->stmtid = ++plpgsql_curr_compile->nstatements;
3076 /* set direction defaults: */
3077 fetch->direction = FETCH_FORWARD;
3078 fetch->how_many = 1;
3079 fetch->expr = NULL;
3080 fetch->returns_multiple_rows = false;
3081
3082 tok = yylex();
3083 if (tok == 0)
3084 yyerror("unexpected end of function definition");
3085
3086 if (tok_is_keyword(tok, &yylval,
3087 K_NEXT, "next"))
3088 {
3089 /* use defaults */
3090 }
3091 else if (tok_is_keyword(tok, &yylval,
3092 K_PRIOR, "prior"))
3093 {
3094 fetch->direction = FETCH_BACKWARD;
3095 }
3096 else if (tok_is_keyword(tok, &yylval,
3097 K_FIRST, "first"))
3098 {
3099 fetch->direction = FETCH_ABSOLUTE;
3100 }
3101 else if (tok_is_keyword(tok, &yylval,
3102 K_LAST, "last"))
3103 {
3104 fetch->direction = FETCH_ABSOLUTE;
3105 fetch->how_many = -1;
3106 }
3107 else if (tok_is_keyword(tok, &yylval,
3108 K_ABSOLUTE, "absolute"))
3109 {
3110 fetch->direction = FETCH_ABSOLUTE;
3111 fetch->expr = read_sql_expression2(K_FROM, K_IN,
3112 "FROM or IN",
3113 NULL);
3114 check_FROM = false;
3115 }
3116 else if (tok_is_keyword(tok, &yylval,
3117 K_RELATIVE, "relative"))
3118 {
3119 fetch->direction = FETCH_RELATIVE;
3120 fetch->expr = read_sql_expression2(K_FROM, K_IN,
3121 "FROM or IN",
3122 NULL);
3123 check_FROM = false;
3124 }
3125 else if (tok_is_keyword(tok, &yylval,
3126 K_ALL, "all"))
3127 {
3128 fetch->how_many = FETCH_ALL;
3129 fetch->returns_multiple_rows = true;
3130 }
3131 else if (tok_is_keyword(tok, &yylval,
3132 K_FORWARD, "forward"))
3133 {
3134 complete_direction(fetch, &check_FROM);
3135 }
3136 else if (tok_is_keyword(tok, &yylval,
3137 K_BACKWARD, "backward"))
3138 {
3139 fetch->direction = FETCH_BACKWARD;
3140 complete_direction(fetch, &check_FROM);
3141 }
3142 else if (tok == K_FROM || tok == K_IN)
3143 {
3144 /* empty direction */
3145 check_FROM = false;
3146 }
3147 else if (tok == T_DATUM)
3148 {
3149 /* Assume there's no direction clause and tok is a cursor name */
3150 plpgsql_push_back_token(tok);
3151 check_FROM = false;
3152 }
3153 else
3154 {
3155 /*
3156 * Assume it's a count expression with no preceding keyword.
3157 * Note: we allow this syntax because core SQL does, but we don't
3158 * document it because of the ambiguity with the omitted-direction
3159 * case. For instance, "MOVE n IN c" will fail if n is a variable.
3160 * Perhaps this can be improved someday, but it's hardly worth a
3161 * lot of work.
3162 */
3163 plpgsql_push_back_token(tok);
3164 fetch->expr = read_sql_expression2(K_FROM, K_IN,
3165 "FROM or IN",
3166 NULL);
3167 fetch->returns_multiple_rows = true;
3168 check_FROM = false;
3169 }
3170
3171 /* check FROM or IN keyword after direction's specification */
3172 if (check_FROM)
3173 {
3174 tok = yylex();
3175 if (tok != K_FROM && tok != K_IN)
3176 yyerror("expected FROM or IN");
3177 }
3178
3179 return fetch;
3180 }
3181
3182 /*
3183 * Process remainder of FETCH/MOVE direction after FORWARD or BACKWARD.
3184 * Allows these cases:
3185 * FORWARD expr, FORWARD ALL, FORWARD
3186 * BACKWARD expr, BACKWARD ALL, BACKWARD
3187 */
3188 static void
complete_direction(PLpgSQL_stmt_fetch * fetch,bool * check_FROM)3189 complete_direction(PLpgSQL_stmt_fetch *fetch, bool *check_FROM)
3190 {
3191 int tok;
3192
3193 tok = yylex();
3194 if (tok == 0)
3195 yyerror("unexpected end of function definition");
3196
3197 if (tok == K_FROM || tok == K_IN)
3198 {
3199 *check_FROM = false;
3200 return;
3201 }
3202
3203 if (tok == K_ALL)
3204 {
3205 fetch->how_many = FETCH_ALL;
3206 fetch->returns_multiple_rows = true;
3207 *check_FROM = true;
3208 return;
3209 }
3210
3211 plpgsql_push_back_token(tok);
3212 fetch->expr = read_sql_expression2(K_FROM, K_IN,
3213 "FROM or IN",
3214 NULL);
3215 fetch->returns_multiple_rows = true;
3216 *check_FROM = false;
3217 }
3218
3219
3220 static PLpgSQL_stmt *
make_return_stmt(int location)3221 make_return_stmt(int location)
3222 {
3223 PLpgSQL_stmt_return *new;
3224
3225 new = palloc0(sizeof(PLpgSQL_stmt_return));
3226 new->cmd_type = PLPGSQL_STMT_RETURN;
3227 new->lineno = plpgsql_location_to_lineno(location);
3228 new->stmtid = ++plpgsql_curr_compile->nstatements;
3229 new->expr = NULL;
3230 new->retvarno = -1;
3231
3232 if (plpgsql_curr_compile->fn_retset)
3233 {
3234 if (yylex() != ';')
3235 ereport(ERROR,
3236 (errcode(ERRCODE_DATATYPE_MISMATCH),
3237 errmsg("RETURN cannot have a parameter in function returning set"),
3238 errhint("Use RETURN NEXT or RETURN QUERY."),
3239 parser_errposition(yylloc)));
3240 }
3241 else if (plpgsql_curr_compile->fn_rettype == VOIDOID)
3242 {
3243 if (yylex() != ';')
3244 {
3245 if (plpgsql_curr_compile->fn_prokind == PROKIND_PROCEDURE)
3246 ereport(ERROR,
3247 (errcode(ERRCODE_SYNTAX_ERROR),
3248 errmsg("RETURN cannot have a parameter in a procedure"),
3249 parser_errposition(yylloc)));
3250 else
3251 ereport(ERROR,
3252 (errcode(ERRCODE_DATATYPE_MISMATCH),
3253 errmsg("RETURN cannot have a parameter in function returning void"),
3254 parser_errposition(yylloc)));
3255 }
3256 }
3257 else if (plpgsql_curr_compile->out_param_varno >= 0)
3258 {
3259 if (yylex() != ';')
3260 ereport(ERROR,
3261 (errcode(ERRCODE_DATATYPE_MISMATCH),
3262 errmsg("RETURN cannot have a parameter in function with OUT parameters"),
3263 parser_errposition(yylloc)));
3264 new->retvarno = plpgsql_curr_compile->out_param_varno;
3265 }
3266 else
3267 {
3268 /*
3269 * We want to special-case simple variable references for efficiency.
3270 * So peek ahead to see if that's what we have.
3271 */
3272 int tok = yylex();
3273
3274 if (tok == T_DATUM && plpgsql_peek() == ';' &&
3275 (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_VAR ||
3276 yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_PROMISE ||
3277 yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
3278 yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC))
3279 {
3280 new->retvarno = yylval.wdatum.datum->dno;
3281 /* eat the semicolon token that we only peeked at above */
3282 tok = yylex();
3283 Assert(tok == ';');
3284 }
3285 else
3286 {
3287 /*
3288 * Not (just) a variable name, so treat as expression.
3289 *
3290 * Note that a well-formed expression is _required_ here;
3291 * anything else is a compile-time error.
3292 */
3293 plpgsql_push_back_token(tok);
3294 new->expr = read_sql_expression(';', ";");
3295 }
3296 }
3297
3298 return (PLpgSQL_stmt *) new;
3299 }
3300
3301
3302 static PLpgSQL_stmt *
make_return_next_stmt(int location)3303 make_return_next_stmt(int location)
3304 {
3305 PLpgSQL_stmt_return_next *new;
3306
3307 if (!plpgsql_curr_compile->fn_retset)
3308 ereport(ERROR,
3309 (errcode(ERRCODE_DATATYPE_MISMATCH),
3310 errmsg("cannot use RETURN NEXT in a non-SETOF function"),
3311 parser_errposition(location)));
3312
3313 new = palloc0(sizeof(PLpgSQL_stmt_return_next));
3314 new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
3315 new->lineno = plpgsql_location_to_lineno(location);
3316 new->stmtid = ++plpgsql_curr_compile->nstatements;
3317 new->expr = NULL;
3318 new->retvarno = -1;
3319
3320 if (plpgsql_curr_compile->out_param_varno >= 0)
3321 {
3322 if (yylex() != ';')
3323 ereport(ERROR,
3324 (errcode(ERRCODE_DATATYPE_MISMATCH),
3325 errmsg("RETURN NEXT cannot have a parameter in function with OUT parameters"),
3326 parser_errposition(yylloc)));
3327 new->retvarno = plpgsql_curr_compile->out_param_varno;
3328 }
3329 else
3330 {
3331 /*
3332 * We want to special-case simple variable references for efficiency.
3333 * So peek ahead to see if that's what we have.
3334 */
3335 int tok = yylex();
3336
3337 if (tok == T_DATUM && plpgsql_peek() == ';' &&
3338 (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_VAR ||
3339 yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_PROMISE ||
3340 yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
3341 yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC))
3342 {
3343 new->retvarno = yylval.wdatum.datum->dno;
3344 /* eat the semicolon token that we only peeked at above */
3345 tok = yylex();
3346 Assert(tok == ';');
3347 }
3348 else
3349 {
3350 /*
3351 * Not (just) a variable name, so treat as expression.
3352 *
3353 * Note that a well-formed expression is _required_ here;
3354 * anything else is a compile-time error.
3355 */
3356 plpgsql_push_back_token(tok);
3357 new->expr = read_sql_expression(';', ";");
3358 }
3359 }
3360
3361 return (PLpgSQL_stmt *) new;
3362 }
3363
3364
3365 static PLpgSQL_stmt *
make_return_query_stmt(int location)3366 make_return_query_stmt(int location)
3367 {
3368 PLpgSQL_stmt_return_query *new;
3369 int tok;
3370
3371 if (!plpgsql_curr_compile->fn_retset)
3372 ereport(ERROR,
3373 (errcode(ERRCODE_DATATYPE_MISMATCH),
3374 errmsg("cannot use RETURN QUERY in a non-SETOF function"),
3375 parser_errposition(location)));
3376
3377 new = palloc0(sizeof(PLpgSQL_stmt_return_query));
3378 new->cmd_type = PLPGSQL_STMT_RETURN_QUERY;
3379 new->lineno = plpgsql_location_to_lineno(location);
3380 new->stmtid = ++plpgsql_curr_compile->nstatements;
3381
3382 /* check for RETURN QUERY EXECUTE */
3383 if ((tok = yylex()) != K_EXECUTE)
3384 {
3385 /* ordinary static query */
3386 plpgsql_push_back_token(tok);
3387 new->query = read_sql_stmt();
3388 }
3389 else
3390 {
3391 /* dynamic SQL */
3392 int term;
3393
3394 new->dynquery = read_sql_expression2(';', K_USING, "; or USING",
3395 &term);
3396 if (term == K_USING)
3397 {
3398 do
3399 {
3400 PLpgSQL_expr *expr;
3401
3402 expr = read_sql_expression2(',', ';', ", or ;", &term);
3403 new->params = lappend(new->params, expr);
3404 } while (term == ',');
3405 }
3406 }
3407
3408 return (PLpgSQL_stmt *) new;
3409 }
3410
3411
3412 /* convenience routine to fetch the name of a T_DATUM */
3413 static char *
NameOfDatum(PLwdatum * wdatum)3414 NameOfDatum(PLwdatum *wdatum)
3415 {
3416 if (wdatum->ident)
3417 return wdatum->ident;
3418 Assert(wdatum->idents != NIL);
3419 return NameListToString(wdatum->idents);
3420 }
3421
3422 static void
check_assignable(PLpgSQL_datum * datum,int location)3423 check_assignable(PLpgSQL_datum *datum, int location)
3424 {
3425 switch (datum->dtype)
3426 {
3427 case PLPGSQL_DTYPE_VAR:
3428 case PLPGSQL_DTYPE_PROMISE:
3429 case PLPGSQL_DTYPE_REC:
3430 if (((PLpgSQL_variable *) datum)->isconst)
3431 ereport(ERROR,
3432 (errcode(ERRCODE_ERROR_IN_ASSIGNMENT),
3433 errmsg("variable \"%s\" is declared CONSTANT",
3434 ((PLpgSQL_variable *) datum)->refname),
3435 parser_errposition(location)));
3436 break;
3437 case PLPGSQL_DTYPE_ROW:
3438 /* always assignable; member vars were checked at compile time */
3439 break;
3440 case PLPGSQL_DTYPE_RECFIELD:
3441 /* assignable if parent record is */
3442 check_assignable(plpgsql_Datums[((PLpgSQL_recfield *) datum)->recparentno],
3443 location);
3444 break;
3445 default:
3446 elog(ERROR, "unrecognized dtype: %d", datum->dtype);
3447 break;
3448 }
3449 }
3450
3451 /*
3452 * Read the argument of an INTO clause. On entry, we have just read the
3453 * INTO keyword.
3454 */
3455 static void
read_into_target(PLpgSQL_variable ** target,bool * strict)3456 read_into_target(PLpgSQL_variable **target, bool *strict)
3457 {
3458 int tok;
3459
3460 /* Set default results */
3461 *target = NULL;
3462 if (strict)
3463 *strict = false;
3464
3465 tok = yylex();
3466 if (strict && tok == K_STRICT)
3467 {
3468 *strict = true;
3469 tok = yylex();
3470 }
3471
3472 /*
3473 * Currently, a row or record variable can be the single INTO target,
3474 * but not a member of a multi-target list. So we throw error if there
3475 * is a comma after it, because that probably means the user tried to
3476 * write a multi-target list. If this ever gets generalized, we should
3477 * probably refactor read_into_scalar_list so it handles all cases.
3478 */
3479 switch (tok)
3480 {
3481 case T_DATUM:
3482 if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
3483 yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)
3484 {
3485 check_assignable(yylval.wdatum.datum, yylloc);
3486 *target = (PLpgSQL_variable *) yylval.wdatum.datum;
3487
3488 if ((tok = yylex()) == ',')
3489 ereport(ERROR,
3490 (errcode(ERRCODE_SYNTAX_ERROR),
3491 errmsg("record variable cannot be part of multiple-item INTO list"),
3492 parser_errposition(yylloc)));
3493 plpgsql_push_back_token(tok);
3494 }
3495 else
3496 {
3497 *target = (PLpgSQL_variable *)
3498 read_into_scalar_list(NameOfDatum(&(yylval.wdatum)),
3499 yylval.wdatum.datum, yylloc);
3500 }
3501 break;
3502
3503 default:
3504 /* just to give a better message than "syntax error" */
3505 current_token_is_not_variable(tok);
3506 }
3507 }
3508
3509 /*
3510 * Given the first datum and name in the INTO list, continue to read
3511 * comma-separated scalar variables until we run out. Then construct
3512 * and return a fake "row" variable that represents the list of
3513 * scalars.
3514 */
3515 static PLpgSQL_row *
read_into_scalar_list(char * initial_name,PLpgSQL_datum * initial_datum,int initial_location)3516 read_into_scalar_list(char *initial_name,
3517 PLpgSQL_datum *initial_datum,
3518 int initial_location)
3519 {
3520 int nfields;
3521 char *fieldnames[1024];
3522 int varnos[1024];
3523 PLpgSQL_row *row;
3524 int tok;
3525
3526 check_assignable(initial_datum, initial_location);
3527 fieldnames[0] = initial_name;
3528 varnos[0] = initial_datum->dno;
3529 nfields = 1;
3530
3531 while ((tok = yylex()) == ',')
3532 {
3533 /* Check for array overflow */
3534 if (nfields >= 1024)
3535 ereport(ERROR,
3536 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3537 errmsg("too many INTO variables specified"),
3538 parser_errposition(yylloc)));
3539
3540 tok = yylex();
3541 switch (tok)
3542 {
3543 case T_DATUM:
3544 check_assignable(yylval.wdatum.datum, yylloc);
3545 if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
3546 yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)
3547 ereport(ERROR,
3548 (errcode(ERRCODE_SYNTAX_ERROR),
3549 errmsg("\"%s\" is not a scalar variable",
3550 NameOfDatum(&(yylval.wdatum))),
3551 parser_errposition(yylloc)));
3552 fieldnames[nfields] = NameOfDatum(&(yylval.wdatum));
3553 varnos[nfields++] = yylval.wdatum.datum->dno;
3554 break;
3555
3556 default:
3557 /* just to give a better message than "syntax error" */
3558 current_token_is_not_variable(tok);
3559 }
3560 }
3561
3562 /*
3563 * We read an extra, non-comma token from yylex(), so push it
3564 * back onto the input stream
3565 */
3566 plpgsql_push_back_token(tok);
3567
3568 row = palloc0(sizeof(PLpgSQL_row));
3569 row->dtype = PLPGSQL_DTYPE_ROW;
3570 row->refname = "(unnamed row)";
3571 row->lineno = plpgsql_location_to_lineno(initial_location);
3572 row->rowtupdesc = NULL;
3573 row->nfields = nfields;
3574 row->fieldnames = palloc(sizeof(char *) * nfields);
3575 row->varnos = palloc(sizeof(int) * nfields);
3576 while (--nfields >= 0)
3577 {
3578 row->fieldnames[nfields] = fieldnames[nfields];
3579 row->varnos[nfields] = varnos[nfields];
3580 }
3581
3582 plpgsql_adddatum((PLpgSQL_datum *)row);
3583
3584 return row;
3585 }
3586
3587 /*
3588 * Convert a single scalar into a "row" list. This is exactly
3589 * like read_into_scalar_list except we never consume any input.
3590 *
3591 * Note: lineno could be computed from location, but since callers
3592 * have it at hand already, we may as well pass it in.
3593 */
3594 static PLpgSQL_row *
make_scalar_list1(char * initial_name,PLpgSQL_datum * initial_datum,int lineno,int location)3595 make_scalar_list1(char *initial_name,
3596 PLpgSQL_datum *initial_datum,
3597 int lineno, int location)
3598 {
3599 PLpgSQL_row *row;
3600
3601 check_assignable(initial_datum, location);
3602
3603 row = palloc0(sizeof(PLpgSQL_row));
3604 row->dtype = PLPGSQL_DTYPE_ROW;
3605 row->refname = "(unnamed row)";
3606 row->lineno = lineno;
3607 row->rowtupdesc = NULL;
3608 row->nfields = 1;
3609 row->fieldnames = palloc(sizeof(char *));
3610 row->varnos = palloc(sizeof(int));
3611 row->fieldnames[0] = initial_name;
3612 row->varnos[0] = initial_datum->dno;
3613
3614 plpgsql_adddatum((PLpgSQL_datum *)row);
3615
3616 return row;
3617 }
3618
3619 /*
3620 * When the PL/pgSQL parser expects to see a SQL statement, it is very
3621 * liberal in what it accepts; for example, we often assume an
3622 * unrecognized keyword is the beginning of a SQL statement. This
3623 * avoids the need to duplicate parts of the SQL grammar in the
3624 * PL/pgSQL grammar, but it means we can accept wildly malformed
3625 * input. To try and catch some of the more obviously invalid input,
3626 * we run the strings we expect to be SQL statements through the main
3627 * SQL parser.
3628 *
3629 * We only invoke the raw parser (not the analyzer); this doesn't do
3630 * any database access and does not check any semantic rules, it just
3631 * checks for basic syntactic correctness. We do this here, rather
3632 * than after parsing has finished, because a malformed SQL statement
3633 * may cause the PL/pgSQL parser to become confused about statement
3634 * borders. So it is best to bail out as early as we can.
3635 *
3636 * It is assumed that "stmt" represents a copy of the function source text
3637 * beginning at offset "location". We use this assumption to transpose
3638 * any error cursor position back to the function source text.
3639 * If no error cursor is provided, we'll just point at "location".
3640 */
3641 static void
check_sql_expr(const char * stmt,RawParseMode parseMode,int location)3642 check_sql_expr(const char *stmt, RawParseMode parseMode, int location)
3643 {
3644 sql_error_callback_arg cbarg;
3645 ErrorContextCallback syntax_errcontext;
3646 MemoryContext oldCxt;
3647
3648 if (!plpgsql_check_syntax)
3649 return;
3650
3651 cbarg.location = location;
3652
3653 syntax_errcontext.callback = plpgsql_sql_error_callback;
3654 syntax_errcontext.arg = &cbarg;
3655 syntax_errcontext.previous = error_context_stack;
3656 error_context_stack = &syntax_errcontext;
3657
3658 oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
3659 (void) raw_parser(stmt, parseMode);
3660 MemoryContextSwitchTo(oldCxt);
3661
3662 /* Restore former ereport callback */
3663 error_context_stack = syntax_errcontext.previous;
3664 }
3665
3666 static void
plpgsql_sql_error_callback(void * arg)3667 plpgsql_sql_error_callback(void *arg)
3668 {
3669 sql_error_callback_arg *cbarg = (sql_error_callback_arg *) arg;
3670 int errpos;
3671
3672 /*
3673 * First, set up internalerrposition to point to the start of the
3674 * statement text within the function text. Note this converts
3675 * location (a byte offset) to a character number.
3676 */
3677 parser_errposition(cbarg->location);
3678
3679 /*
3680 * If the core parser provided an error position, transpose it.
3681 * Note we are dealing with 1-based character numbers at this point.
3682 */
3683 errpos = geterrposition();
3684 if (errpos > 0)
3685 {
3686 int myerrpos = getinternalerrposition();
3687
3688 if (myerrpos > 0) /* safety check */
3689 internalerrposition(myerrpos + errpos - 1);
3690 }
3691
3692 /* In any case, flush errposition --- we want internalerrposition only */
3693 errposition(0);
3694 }
3695
3696 /*
3697 * Parse a SQL datatype name and produce a PLpgSQL_type structure.
3698 *
3699 * The heavy lifting is done elsewhere. Here we are only concerned
3700 * with setting up an errcontext link that will let us give an error
3701 * cursor pointing into the plpgsql function source, if necessary.
3702 * This is handled the same as in check_sql_expr(), and we likewise
3703 * expect that the given string is a copy from the source text.
3704 */
3705 static PLpgSQL_type *
parse_datatype(const char * string,int location)3706 parse_datatype(const char *string, int location)
3707 {
3708 TypeName *typeName;
3709 Oid type_id;
3710 int32 typmod;
3711 sql_error_callback_arg cbarg;
3712 ErrorContextCallback syntax_errcontext;
3713
3714 cbarg.location = location;
3715
3716 syntax_errcontext.callback = plpgsql_sql_error_callback;
3717 syntax_errcontext.arg = &cbarg;
3718 syntax_errcontext.previous = error_context_stack;
3719 error_context_stack = &syntax_errcontext;
3720
3721 /* Let the main parser try to parse it under standard SQL rules */
3722 typeName = typeStringToTypeName(string);
3723 typenameTypeIdAndMod(NULL, typeName, &type_id, &typmod);
3724
3725 /* Restore former ereport callback */
3726 error_context_stack = syntax_errcontext.previous;
3727
3728 /* Okay, build a PLpgSQL_type data structure for it */
3729 return plpgsql_build_datatype(type_id, typmod,
3730 plpgsql_curr_compile->fn_input_collation,
3731 typeName);
3732 }
3733
3734 /*
3735 * Check block starting and ending labels match.
3736 */
3737 static void
check_labels(const char * start_label,const char * end_label,int end_location)3738 check_labels(const char *start_label, const char *end_label, int end_location)
3739 {
3740 if (end_label)
3741 {
3742 if (!start_label)
3743 ereport(ERROR,
3744 (errcode(ERRCODE_SYNTAX_ERROR),
3745 errmsg("end label \"%s\" specified for unlabeled block",
3746 end_label),
3747 parser_errposition(end_location)));
3748
3749 if (strcmp(start_label, end_label) != 0)
3750 ereport(ERROR,
3751 (errcode(ERRCODE_SYNTAX_ERROR),
3752 errmsg("end label \"%s\" differs from block's label \"%s\"",
3753 end_label, start_label),
3754 parser_errposition(end_location)));
3755 }
3756 }
3757
3758 /*
3759 * Read the arguments (if any) for a cursor, followed by the until token
3760 *
3761 * If cursor has no args, just swallow the until token and return NULL.
3762 * If it does have args, we expect to see "( arg [, arg ...] )" followed
3763 * by the until token, where arg may be a plain expression, or a named
3764 * parameter assignment of the form argname := expr. Consume all that and
3765 * return a SELECT query that evaluates the expression(s) (without the outer
3766 * parens).
3767 */
3768 static PLpgSQL_expr *
read_cursor_args(PLpgSQL_var * cursor,int until)3769 read_cursor_args(PLpgSQL_var *cursor, int until)
3770 {
3771 PLpgSQL_expr *expr;
3772 PLpgSQL_row *row;
3773 int tok;
3774 int argc;
3775 char **argv;
3776 StringInfoData ds;
3777 bool any_named = false;
3778
3779 tok = yylex();
3780 if (cursor->cursor_explicit_argrow < 0)
3781 {
3782 /* No arguments expected */
3783 if (tok == '(')
3784 ereport(ERROR,
3785 (errcode(ERRCODE_SYNTAX_ERROR),
3786 errmsg("cursor \"%s\" has no arguments",
3787 cursor->refname),
3788 parser_errposition(yylloc)));
3789
3790 if (tok != until)
3791 yyerror("syntax error");
3792
3793 return NULL;
3794 }
3795
3796 /* Else better provide arguments */
3797 if (tok != '(')
3798 ereport(ERROR,
3799 (errcode(ERRCODE_SYNTAX_ERROR),
3800 errmsg("cursor \"%s\" has arguments",
3801 cursor->refname),
3802 parser_errposition(yylloc)));
3803
3804 /*
3805 * Read the arguments, one by one.
3806 */
3807 row = (PLpgSQL_row *) plpgsql_Datums[cursor->cursor_explicit_argrow];
3808 argv = (char **) palloc0(row->nfields * sizeof(char *));
3809
3810 for (argc = 0; argc < row->nfields; argc++)
3811 {
3812 PLpgSQL_expr *item;
3813 int endtoken;
3814 int argpos;
3815 int tok1,
3816 tok2;
3817 int arglocation;
3818
3819 /* Check if it's a named parameter: "param := value" */
3820 plpgsql_peek2(&tok1, &tok2, &arglocation, NULL);
3821 if (tok1 == IDENT && tok2 == COLON_EQUALS)
3822 {
3823 char *argname;
3824 IdentifierLookup save_IdentifierLookup;
3825
3826 /* Read the argument name, ignoring any matching variable */
3827 save_IdentifierLookup = plpgsql_IdentifierLookup;
3828 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_DECLARE;
3829 yylex();
3830 argname = yylval.str;
3831 plpgsql_IdentifierLookup = save_IdentifierLookup;
3832
3833 /* Match argument name to cursor arguments */
3834 for (argpos = 0; argpos < row->nfields; argpos++)
3835 {
3836 if (strcmp(row->fieldnames[argpos], argname) == 0)
3837 break;
3838 }
3839 if (argpos == row->nfields)
3840 ereport(ERROR,
3841 (errcode(ERRCODE_SYNTAX_ERROR),
3842 errmsg("cursor \"%s\" has no argument named \"%s\"",
3843 cursor->refname, argname),
3844 parser_errposition(yylloc)));
3845
3846 /*
3847 * Eat the ":=". We already peeked, so the error should never
3848 * happen.
3849 */
3850 tok2 = yylex();
3851 if (tok2 != COLON_EQUALS)
3852 yyerror("syntax error");
3853
3854 any_named = true;
3855 }
3856 else
3857 argpos = argc;
3858
3859 if (argv[argpos] != NULL)
3860 ereport(ERROR,
3861 (errcode(ERRCODE_SYNTAX_ERROR),
3862 errmsg("value for parameter \"%s\" of cursor \"%s\" specified more than once",
3863 row->fieldnames[argpos], cursor->refname),
3864 parser_errposition(arglocation)));
3865
3866 /*
3867 * Read the value expression. To provide the user with meaningful
3868 * parse error positions, we check the syntax immediately, instead of
3869 * checking the final expression that may have the arguments
3870 * reordered. Trailing whitespace must not be trimmed, because
3871 * otherwise input of the form (param -- comment\n, param) would be
3872 * translated into a form where the second parameter is commented
3873 * out.
3874 */
3875 item = read_sql_construct(',', ')', 0,
3876 ",\" or \")",
3877 RAW_PARSE_PLPGSQL_EXPR,
3878 true, true,
3879 false, /* do not trim */
3880 NULL, &endtoken);
3881
3882 argv[argpos] = item->query;
3883
3884 if (endtoken == ')' && !(argc == row->nfields - 1))
3885 ereport(ERROR,
3886 (errcode(ERRCODE_SYNTAX_ERROR),
3887 errmsg("not enough arguments for cursor \"%s\"",
3888 cursor->refname),
3889 parser_errposition(yylloc)));
3890
3891 if (endtoken == ',' && (argc == row->nfields - 1))
3892 ereport(ERROR,
3893 (errcode(ERRCODE_SYNTAX_ERROR),
3894 errmsg("too many arguments for cursor \"%s\"",
3895 cursor->refname),
3896 parser_errposition(yylloc)));
3897 }
3898
3899 /* Make positional argument list */
3900 initStringInfo(&ds);
3901 for (argc = 0; argc < row->nfields; argc++)
3902 {
3903 Assert(argv[argc] != NULL);
3904
3905 /*
3906 * Because named notation allows permutated argument lists, include
3907 * the parameter name for meaningful runtime errors.
3908 */
3909 appendStringInfoString(&ds, argv[argc]);
3910 if (any_named)
3911 appendStringInfo(&ds, " AS %s",
3912 quote_identifier(row->fieldnames[argc]));
3913 if (argc < row->nfields - 1)
3914 appendStringInfoString(&ds, ", ");
3915 }
3916
3917 expr = palloc0(sizeof(PLpgSQL_expr));
3918 expr->query = pstrdup(ds.data);
3919 expr->parseMode = RAW_PARSE_PLPGSQL_EXPR;
3920 expr->plan = NULL;
3921 expr->paramnos = NULL;
3922 expr->target_param = -1;
3923 expr->ns = plpgsql_ns_top();
3924 pfree(ds.data);
3925
3926 /* Next we'd better find the until token */
3927 tok = yylex();
3928 if (tok != until)
3929 yyerror("syntax error");
3930
3931 return expr;
3932 }
3933
3934 /*
3935 * Parse RAISE ... USING options
3936 */
3937 static List *
read_raise_options(void)3938 read_raise_options(void)
3939 {
3940 List *result = NIL;
3941
3942 for (;;)
3943 {
3944 PLpgSQL_raise_option *opt;
3945 int tok;
3946
3947 if ((tok = yylex()) == 0)
3948 yyerror("unexpected end of function definition");
3949
3950 opt = (PLpgSQL_raise_option *) palloc(sizeof(PLpgSQL_raise_option));
3951
3952 if (tok_is_keyword(tok, &yylval,
3953 K_ERRCODE, "errcode"))
3954 opt->opt_type = PLPGSQL_RAISEOPTION_ERRCODE;
3955 else if (tok_is_keyword(tok, &yylval,
3956 K_MESSAGE, "message"))
3957 opt->opt_type = PLPGSQL_RAISEOPTION_MESSAGE;
3958 else if (tok_is_keyword(tok, &yylval,
3959 K_DETAIL, "detail"))
3960 opt->opt_type = PLPGSQL_RAISEOPTION_DETAIL;
3961 else if (tok_is_keyword(tok, &yylval,
3962 K_HINT, "hint"))
3963 opt->opt_type = PLPGSQL_RAISEOPTION_HINT;
3964 else if (tok_is_keyword(tok, &yylval,
3965 K_COLUMN, "column"))
3966 opt->opt_type = PLPGSQL_RAISEOPTION_COLUMN;
3967 else if (tok_is_keyword(tok, &yylval,
3968 K_CONSTRAINT, "constraint"))
3969 opt->opt_type = PLPGSQL_RAISEOPTION_CONSTRAINT;
3970 else if (tok_is_keyword(tok, &yylval,
3971 K_DATATYPE, "datatype"))
3972 opt->opt_type = PLPGSQL_RAISEOPTION_DATATYPE;
3973 else if (tok_is_keyword(tok, &yylval,
3974 K_TABLE, "table"))
3975 opt->opt_type = PLPGSQL_RAISEOPTION_TABLE;
3976 else if (tok_is_keyword(tok, &yylval,
3977 K_SCHEMA, "schema"))
3978 opt->opt_type = PLPGSQL_RAISEOPTION_SCHEMA;
3979 else
3980 yyerror("unrecognized RAISE statement option");
3981
3982 tok = yylex();
3983 if (tok != '=' && tok != COLON_EQUALS)
3984 yyerror("syntax error, expected \"=\"");
3985
3986 opt->expr = read_sql_expression2(',', ';', ", or ;", &tok);
3987
3988 result = lappend(result, opt);
3989
3990 if (tok == ';')
3991 break;
3992 }
3993
3994 return result;
3995 }
3996
3997 /*
3998 * Check that the number of parameter placeholders in the message matches the
3999 * number of parameters passed to it, if a message was given.
4000 */
4001 static void
check_raise_parameters(PLpgSQL_stmt_raise * stmt)4002 check_raise_parameters(PLpgSQL_stmt_raise *stmt)
4003 {
4004 char *cp;
4005 int expected_nparams = 0;
4006
4007 if (stmt->message == NULL)
4008 return;
4009
4010 for (cp = stmt->message; *cp; cp++)
4011 {
4012 if (cp[0] == '%')
4013 {
4014 /* ignore literal % characters */
4015 if (cp[1] == '%')
4016 cp++;
4017 else
4018 expected_nparams++;
4019 }
4020 }
4021
4022 if (expected_nparams < list_length(stmt->params))
4023 ereport(ERROR,
4024 (errcode(ERRCODE_SYNTAX_ERROR),
4025 errmsg("too many parameters specified for RAISE")));
4026 if (expected_nparams > list_length(stmt->params))
4027 ereport(ERROR,
4028 (errcode(ERRCODE_SYNTAX_ERROR),
4029 errmsg("too few parameters specified for RAISE")));
4030 }
4031
4032 /*
4033 * Fix up CASE statement
4034 */
4035 static PLpgSQL_stmt *
make_case(int location,PLpgSQL_expr * t_expr,List * case_when_list,List * else_stmts)4036 make_case(int location, PLpgSQL_expr *t_expr,
4037 List *case_when_list, List *else_stmts)
4038 {
4039 PLpgSQL_stmt_case *new;
4040
4041 new = palloc(sizeof(PLpgSQL_stmt_case));
4042 new->cmd_type = PLPGSQL_STMT_CASE;
4043 new->lineno = plpgsql_location_to_lineno(location);
4044 new->stmtid = ++plpgsql_curr_compile->nstatements;
4045 new->t_expr = t_expr;
4046 new->t_varno = 0;
4047 new->case_when_list = case_when_list;
4048 new->have_else = (else_stmts != NIL);
4049 /* Get rid of list-with-NULL hack */
4050 if (list_length(else_stmts) == 1 && linitial(else_stmts) == NULL)
4051 new->else_stmts = NIL;
4052 else
4053 new->else_stmts = else_stmts;
4054
4055 /*
4056 * When test expression is present, we create a var for it and then
4057 * convert all the WHEN expressions to "VAR IN (original_expression)".
4058 * This is a bit klugy, but okay since we haven't yet done more than
4059 * read the expressions as text. (Note that previous parsing won't
4060 * have complained if the WHEN ... THEN expression contained multiple
4061 * comma-separated values.)
4062 */
4063 if (t_expr)
4064 {
4065 char varname[32];
4066 PLpgSQL_var *t_var;
4067 ListCell *l;
4068
4069 /* use a name unlikely to collide with any user names */
4070 snprintf(varname, sizeof(varname), "__Case__Variable_%d__",
4071 plpgsql_nDatums);
4072
4073 /*
4074 * We don't yet know the result datatype of t_expr. Build the
4075 * variable as if it were INT4; we'll fix this at runtime if needed.
4076 */
4077 t_var = (PLpgSQL_var *)
4078 plpgsql_build_variable(varname, new->lineno,
4079 plpgsql_build_datatype(INT4OID,
4080 -1,
4081 InvalidOid,
4082 NULL),
4083 true);
4084 new->t_varno = t_var->dno;
4085
4086 foreach(l, case_when_list)
4087 {
4088 PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
4089 PLpgSQL_expr *expr = cwt->expr;
4090 StringInfoData ds;
4091
4092 /* We expect to have expressions not statements */
4093 Assert(expr->parseMode == RAW_PARSE_PLPGSQL_EXPR);
4094
4095 /* Do the string hacking */
4096 initStringInfo(&ds);
4097
4098 appendStringInfo(&ds, "\"%s\" IN (%s)",
4099 varname, expr->query);
4100
4101 pfree(expr->query);
4102 expr->query = pstrdup(ds.data);
4103 /* Adjust expr's namespace to include the case variable */
4104 expr->ns = plpgsql_ns_top();
4105
4106 pfree(ds.data);
4107 }
4108 }
4109
4110 return (PLpgSQL_stmt *) new;
4111 }
4112