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