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