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