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