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