1 /*-------------------------------------------------------------------------
2  *
3  * pl_funcs.c		- Misc functions for the PL/pgSQL
4  *			  procedural language
5  *
6  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/pl/plpgsql/src/pl_funcs.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "plpgsql.h"
17 
18 #include "utils/memutils.h"
19 
20 
21 /* ----------
22  * Local variables for namespace handling
23  *
24  * The namespace structure actually forms a tree, of which only one linear
25  * list or "chain" (from the youngest item to the root) is accessible from
26  * any one plpgsql statement.  During initial parsing of a function, ns_top
27  * points to the youngest item accessible from the block currently being
28  * parsed.  We store the entire tree, however, since at runtime we will need
29  * to access the chain that's relevant to any one statement.
30  *
31  * Block boundaries in the namespace chain are marked by PLPGSQL_NSTYPE_LABEL
32  * items.
33  * ----------
34  */
35 static PLpgSQL_nsitem *ns_top = NULL;
36 
37 
38 /* ----------
39  * plpgsql_ns_init			Initialize namespace processing for a new function
40  * ----------
41  */
42 void
plpgsql_ns_init(void)43 plpgsql_ns_init(void)
44 {
45 	ns_top = NULL;
46 }
47 
48 
49 /* ----------
50  * plpgsql_ns_push			Create a new namespace level
51  * ----------
52  */
53 void
plpgsql_ns_push(const char * label,enum PLpgSQL_label_types label_type)54 plpgsql_ns_push(const char *label, enum PLpgSQL_label_types label_type)
55 {
56 	if (label == NULL)
57 		label = "";
58 	plpgsql_ns_additem(PLPGSQL_NSTYPE_LABEL, (int) label_type, label);
59 }
60 
61 
62 /* ----------
63  * plpgsql_ns_pop			Pop entries back to (and including) the last label
64  * ----------
65  */
66 void
plpgsql_ns_pop(void)67 plpgsql_ns_pop(void)
68 {
69 	Assert(ns_top != NULL);
70 	while (ns_top->itemtype != PLPGSQL_NSTYPE_LABEL)
71 		ns_top = ns_top->prev;
72 	ns_top = ns_top->prev;
73 }
74 
75 
76 /* ----------
77  * plpgsql_ns_top			Fetch the current namespace chain end
78  * ----------
79  */
80 PLpgSQL_nsitem *
plpgsql_ns_top(void)81 plpgsql_ns_top(void)
82 {
83 	return ns_top;
84 }
85 
86 
87 /* ----------
88  * plpgsql_ns_additem		Add an item to the current namespace chain
89  * ----------
90  */
91 void
plpgsql_ns_additem(int itemtype,int itemno,const char * name)92 plpgsql_ns_additem(int itemtype, int itemno, const char *name)
93 {
94 	PLpgSQL_nsitem *nse;
95 
96 	Assert(name != NULL);
97 	/* first item added must be a label */
98 	Assert(ns_top != NULL || itemtype == PLPGSQL_NSTYPE_LABEL);
99 
100 	nse = palloc(offsetof(PLpgSQL_nsitem, name) +strlen(name) + 1);
101 	nse->itemtype = itemtype;
102 	nse->itemno = itemno;
103 	nse->prev = ns_top;
104 	strcpy(nse->name, name);
105 	ns_top = nse;
106 }
107 
108 
109 /* ----------
110  * plpgsql_ns_lookup		Lookup an identifier in the given namespace chain
111  *
112  * Note that this only searches for variables, not labels.
113  *
114  * If localmode is TRUE, only the topmost block level is searched.
115  *
116  * name1 must be non-NULL.  Pass NULL for name2 and/or name3 if parsing a name
117  * with fewer than three components.
118  *
119  * If names_used isn't NULL, *names_used receives the number of names
120  * matched: 0 if no match, 1 if name1 matched an unqualified variable name,
121  * 2 if name1 and name2 matched a block label + variable name.
122  *
123  * Note that name3 is never directly matched to anything.  However, if it
124  * isn't NULL, we will disregard qualified matches to scalar variables.
125  * Similarly, if name2 isn't NULL, we disregard unqualified matches to
126  * scalar variables.
127  * ----------
128  */
129 PLpgSQL_nsitem *
plpgsql_ns_lookup(PLpgSQL_nsitem * ns_cur,bool localmode,const char * name1,const char * name2,const char * name3,int * names_used)130 plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode,
131 				  const char *name1, const char *name2, const char *name3,
132 				  int *names_used)
133 {
134 	/* Outer loop iterates once per block level in the namespace chain */
135 	while (ns_cur != NULL)
136 	{
137 		PLpgSQL_nsitem *nsitem;
138 
139 		/* Check this level for unqualified match to variable name */
140 		for (nsitem = ns_cur;
141 			 nsitem->itemtype != PLPGSQL_NSTYPE_LABEL;
142 			 nsitem = nsitem->prev)
143 		{
144 			if (strcmp(nsitem->name, name1) == 0)
145 			{
146 				if (name2 == NULL ||
147 					nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
148 				{
149 					if (names_used)
150 						*names_used = 1;
151 					return nsitem;
152 				}
153 			}
154 		}
155 
156 		/* Check this level for qualified match to variable name */
157 		if (name2 != NULL &&
158 			strcmp(nsitem->name, name1) == 0)
159 		{
160 			for (nsitem = ns_cur;
161 				 nsitem->itemtype != PLPGSQL_NSTYPE_LABEL;
162 				 nsitem = nsitem->prev)
163 			{
164 				if (strcmp(nsitem->name, name2) == 0)
165 				{
166 					if (name3 == NULL ||
167 						nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
168 					{
169 						if (names_used)
170 							*names_used = 2;
171 						return nsitem;
172 					}
173 				}
174 			}
175 		}
176 
177 		if (localmode)
178 			break;				/* do not look into upper levels */
179 
180 		ns_cur = nsitem->prev;
181 	}
182 
183 	/* This is just to suppress possibly-uninitialized-variable warnings */
184 	if (names_used)
185 		*names_used = 0;
186 	return NULL;				/* No match found */
187 }
188 
189 
190 /* ----------
191  * plpgsql_ns_lookup_label		Lookup a label in the given namespace chain
192  * ----------
193  */
194 PLpgSQL_nsitem *
plpgsql_ns_lookup_label(PLpgSQL_nsitem * ns_cur,const char * name)195 plpgsql_ns_lookup_label(PLpgSQL_nsitem *ns_cur, const char *name)
196 {
197 	while (ns_cur != NULL)
198 	{
199 		if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL &&
200 			strcmp(ns_cur->name, name) == 0)
201 			return ns_cur;
202 		ns_cur = ns_cur->prev;
203 	}
204 
205 	return NULL;				/* label not found */
206 }
207 
208 
209 /* ----------
210  * plpgsql_ns_find_nearest_loop		Find innermost loop label in namespace chain
211  * ----------
212  */
213 PLpgSQL_nsitem *
plpgsql_ns_find_nearest_loop(PLpgSQL_nsitem * ns_cur)214 plpgsql_ns_find_nearest_loop(PLpgSQL_nsitem *ns_cur)
215 {
216 	while (ns_cur != NULL)
217 	{
218 		if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL &&
219 			ns_cur->itemno == PLPGSQL_LABEL_LOOP)
220 			return ns_cur;
221 		ns_cur = ns_cur->prev;
222 	}
223 
224 	return NULL;				/* no loop found */
225 }
226 
227 
228 /*
229  * Statement type as a string, for use in error messages etc.
230  */
231 const char *
plpgsql_stmt_typename(PLpgSQL_stmt * stmt)232 plpgsql_stmt_typename(PLpgSQL_stmt *stmt)
233 {
234 	switch ((enum PLpgSQL_stmt_types) stmt->cmd_type)
235 	{
236 		case PLPGSQL_STMT_BLOCK:
237 			return _("statement block");
238 		case PLPGSQL_STMT_ASSIGN:
239 			return _("assignment");
240 		case PLPGSQL_STMT_IF:
241 			return "IF";
242 		case PLPGSQL_STMT_CASE:
243 			return "CASE";
244 		case PLPGSQL_STMT_LOOP:
245 			return "LOOP";
246 		case PLPGSQL_STMT_WHILE:
247 			return "WHILE";
248 		case PLPGSQL_STMT_FORI:
249 			return _("FOR with integer loop variable");
250 		case PLPGSQL_STMT_FORS:
251 			return _("FOR over SELECT rows");
252 		case PLPGSQL_STMT_FORC:
253 			return _("FOR over cursor");
254 		case PLPGSQL_STMT_FOREACH_A:
255 			return _("FOREACH over array");
256 		case PLPGSQL_STMT_EXIT:
257 			return ((PLpgSQL_stmt_exit *) stmt)->is_exit ? "EXIT" : "CONTINUE";
258 		case PLPGSQL_STMT_RETURN:
259 			return "RETURN";
260 		case PLPGSQL_STMT_RETURN_NEXT:
261 			return "RETURN NEXT";
262 		case PLPGSQL_STMT_RETURN_QUERY:
263 			return "RETURN QUERY";
264 		case PLPGSQL_STMT_RAISE:
265 			return "RAISE";
266 		case PLPGSQL_STMT_ASSERT:
267 			return "ASSERT";
268 		case PLPGSQL_STMT_EXECSQL:
269 			return _("SQL statement");
270 		case PLPGSQL_STMT_DYNEXECUTE:
271 			return "EXECUTE";
272 		case PLPGSQL_STMT_DYNFORS:
273 			return _("FOR over EXECUTE statement");
274 		case PLPGSQL_STMT_GETDIAG:
275 			return ((PLpgSQL_stmt_getdiag *) stmt)->is_stacked ?
276 				"GET STACKED DIAGNOSTICS" : "GET DIAGNOSTICS";
277 		case PLPGSQL_STMT_OPEN:
278 			return "OPEN";
279 		case PLPGSQL_STMT_FETCH:
280 			return ((PLpgSQL_stmt_fetch *) stmt)->is_move ? "MOVE" : "FETCH";
281 		case PLPGSQL_STMT_CLOSE:
282 			return "CLOSE";
283 		case PLPGSQL_STMT_PERFORM:
284 			return "PERFORM";
285 	}
286 
287 	return "unknown";
288 }
289 
290 /*
291  * GET DIAGNOSTICS item name as a string, for use in error messages etc.
292  */
293 const char *
plpgsql_getdiag_kindname(int kind)294 plpgsql_getdiag_kindname(int kind)
295 {
296 	switch (kind)
297 	{
298 		case PLPGSQL_GETDIAG_ROW_COUNT:
299 			return "ROW_COUNT";
300 		case PLPGSQL_GETDIAG_RESULT_OID:
301 			return "RESULT_OID";
302 		case PLPGSQL_GETDIAG_CONTEXT:
303 			return "PG_CONTEXT";
304 		case PLPGSQL_GETDIAG_ERROR_CONTEXT:
305 			return "PG_EXCEPTION_CONTEXT";
306 		case PLPGSQL_GETDIAG_ERROR_DETAIL:
307 			return "PG_EXCEPTION_DETAIL";
308 		case PLPGSQL_GETDIAG_ERROR_HINT:
309 			return "PG_EXCEPTION_HINT";
310 		case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
311 			return "RETURNED_SQLSTATE";
312 		case PLPGSQL_GETDIAG_COLUMN_NAME:
313 			return "COLUMN_NAME";
314 		case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
315 			return "CONSTRAINT_NAME";
316 		case PLPGSQL_GETDIAG_DATATYPE_NAME:
317 			return "PG_DATATYPE_NAME";
318 		case PLPGSQL_GETDIAG_MESSAGE_TEXT:
319 			return "MESSAGE_TEXT";
320 		case PLPGSQL_GETDIAG_TABLE_NAME:
321 			return "TABLE_NAME";
322 		case PLPGSQL_GETDIAG_SCHEMA_NAME:
323 			return "SCHEMA_NAME";
324 	}
325 
326 	return "unknown";
327 }
328 
329 
330 /**********************************************************************
331  * Release memory when a PL/pgSQL function is no longer needed
332  *
333  * The code for recursing through the function tree is really only
334  * needed to locate PLpgSQL_expr nodes, which may contain references
335  * to saved SPI Plans that must be freed.  The function tree itself,
336  * along with subsidiary data, is freed in one swoop by freeing the
337  * function's permanent memory context.
338  **********************************************************************/
339 static void free_stmt(PLpgSQL_stmt *stmt);
340 static void free_block(PLpgSQL_stmt_block *block);
341 static void free_assign(PLpgSQL_stmt_assign *stmt);
342 static void free_if(PLpgSQL_stmt_if *stmt);
343 static void free_case(PLpgSQL_stmt_case *stmt);
344 static void free_loop(PLpgSQL_stmt_loop *stmt);
345 static void free_while(PLpgSQL_stmt_while *stmt);
346 static void free_fori(PLpgSQL_stmt_fori *stmt);
347 static void free_fors(PLpgSQL_stmt_fors *stmt);
348 static void free_forc(PLpgSQL_stmt_forc *stmt);
349 static void free_foreach_a(PLpgSQL_stmt_foreach_a *stmt);
350 static void free_exit(PLpgSQL_stmt_exit *stmt);
351 static void free_return(PLpgSQL_stmt_return *stmt);
352 static void free_return_next(PLpgSQL_stmt_return_next *stmt);
353 static void free_return_query(PLpgSQL_stmt_return_query *stmt);
354 static void free_raise(PLpgSQL_stmt_raise *stmt);
355 static void free_assert(PLpgSQL_stmt_assert *stmt);
356 static void free_execsql(PLpgSQL_stmt_execsql *stmt);
357 static void free_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
358 static void free_dynfors(PLpgSQL_stmt_dynfors *stmt);
359 static void free_getdiag(PLpgSQL_stmt_getdiag *stmt);
360 static void free_open(PLpgSQL_stmt_open *stmt);
361 static void free_fetch(PLpgSQL_stmt_fetch *stmt);
362 static void free_close(PLpgSQL_stmt_close *stmt);
363 static void free_perform(PLpgSQL_stmt_perform *stmt);
364 static void free_expr(PLpgSQL_expr *expr);
365 
366 
367 static void
free_stmt(PLpgSQL_stmt * stmt)368 free_stmt(PLpgSQL_stmt *stmt)
369 {
370 	switch ((enum PLpgSQL_stmt_types) stmt->cmd_type)
371 	{
372 		case PLPGSQL_STMT_BLOCK:
373 			free_block((PLpgSQL_stmt_block *) stmt);
374 			break;
375 		case PLPGSQL_STMT_ASSIGN:
376 			free_assign((PLpgSQL_stmt_assign *) stmt);
377 			break;
378 		case PLPGSQL_STMT_IF:
379 			free_if((PLpgSQL_stmt_if *) stmt);
380 			break;
381 		case PLPGSQL_STMT_CASE:
382 			free_case((PLpgSQL_stmt_case *) stmt);
383 			break;
384 		case PLPGSQL_STMT_LOOP:
385 			free_loop((PLpgSQL_stmt_loop *) stmt);
386 			break;
387 		case PLPGSQL_STMT_WHILE:
388 			free_while((PLpgSQL_stmt_while *) stmt);
389 			break;
390 		case PLPGSQL_STMT_FORI:
391 			free_fori((PLpgSQL_stmt_fori *) stmt);
392 			break;
393 		case PLPGSQL_STMT_FORS:
394 			free_fors((PLpgSQL_stmt_fors *) stmt);
395 			break;
396 		case PLPGSQL_STMT_FORC:
397 			free_forc((PLpgSQL_stmt_forc *) stmt);
398 			break;
399 		case PLPGSQL_STMT_FOREACH_A:
400 			free_foreach_a((PLpgSQL_stmt_foreach_a *) stmt);
401 			break;
402 		case PLPGSQL_STMT_EXIT:
403 			free_exit((PLpgSQL_stmt_exit *) stmt);
404 			break;
405 		case PLPGSQL_STMT_RETURN:
406 			free_return((PLpgSQL_stmt_return *) stmt);
407 			break;
408 		case PLPGSQL_STMT_RETURN_NEXT:
409 			free_return_next((PLpgSQL_stmt_return_next *) stmt);
410 			break;
411 		case PLPGSQL_STMT_RETURN_QUERY:
412 			free_return_query((PLpgSQL_stmt_return_query *) stmt);
413 			break;
414 		case PLPGSQL_STMT_RAISE:
415 			free_raise((PLpgSQL_stmt_raise *) stmt);
416 			break;
417 		case PLPGSQL_STMT_ASSERT:
418 			free_assert((PLpgSQL_stmt_assert *) stmt);
419 			break;
420 		case PLPGSQL_STMT_EXECSQL:
421 			free_execsql((PLpgSQL_stmt_execsql *) stmt);
422 			break;
423 		case PLPGSQL_STMT_DYNEXECUTE:
424 			free_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
425 			break;
426 		case PLPGSQL_STMT_DYNFORS:
427 			free_dynfors((PLpgSQL_stmt_dynfors *) stmt);
428 			break;
429 		case PLPGSQL_STMT_GETDIAG:
430 			free_getdiag((PLpgSQL_stmt_getdiag *) stmt);
431 			break;
432 		case PLPGSQL_STMT_OPEN:
433 			free_open((PLpgSQL_stmt_open *) stmt);
434 			break;
435 		case PLPGSQL_STMT_FETCH:
436 			free_fetch((PLpgSQL_stmt_fetch *) stmt);
437 			break;
438 		case PLPGSQL_STMT_CLOSE:
439 			free_close((PLpgSQL_stmt_close *) stmt);
440 			break;
441 		case PLPGSQL_STMT_PERFORM:
442 			free_perform((PLpgSQL_stmt_perform *) stmt);
443 			break;
444 		default:
445 			elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
446 			break;
447 	}
448 }
449 
450 static void
free_stmts(List * stmts)451 free_stmts(List *stmts)
452 {
453 	ListCell   *s;
454 
455 	foreach(s, stmts)
456 	{
457 		free_stmt((PLpgSQL_stmt *) lfirst(s));
458 	}
459 }
460 
461 static void
free_block(PLpgSQL_stmt_block * block)462 free_block(PLpgSQL_stmt_block *block)
463 {
464 	free_stmts(block->body);
465 	if (block->exceptions)
466 	{
467 		ListCell   *e;
468 
469 		foreach(e, block->exceptions->exc_list)
470 		{
471 			PLpgSQL_exception *exc = (PLpgSQL_exception *) lfirst(e);
472 
473 			free_stmts(exc->action);
474 		}
475 	}
476 }
477 
478 static void
free_assign(PLpgSQL_stmt_assign * stmt)479 free_assign(PLpgSQL_stmt_assign *stmt)
480 {
481 	free_expr(stmt->expr);
482 }
483 
484 static void
free_if(PLpgSQL_stmt_if * stmt)485 free_if(PLpgSQL_stmt_if *stmt)
486 {
487 	ListCell   *l;
488 
489 	free_expr(stmt->cond);
490 	free_stmts(stmt->then_body);
491 	foreach(l, stmt->elsif_list)
492 	{
493 		PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(l);
494 
495 		free_expr(elif->cond);
496 		free_stmts(elif->stmts);
497 	}
498 	free_stmts(stmt->else_body);
499 }
500 
501 static void
free_case(PLpgSQL_stmt_case * stmt)502 free_case(PLpgSQL_stmt_case *stmt)
503 {
504 	ListCell   *l;
505 
506 	free_expr(stmt->t_expr);
507 	foreach(l, stmt->case_when_list)
508 	{
509 		PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
510 
511 		free_expr(cwt->expr);
512 		free_stmts(cwt->stmts);
513 	}
514 	free_stmts(stmt->else_stmts);
515 }
516 
517 static void
free_loop(PLpgSQL_stmt_loop * stmt)518 free_loop(PLpgSQL_stmt_loop *stmt)
519 {
520 	free_stmts(stmt->body);
521 }
522 
523 static void
free_while(PLpgSQL_stmt_while * stmt)524 free_while(PLpgSQL_stmt_while *stmt)
525 {
526 	free_expr(stmt->cond);
527 	free_stmts(stmt->body);
528 }
529 
530 static void
free_fori(PLpgSQL_stmt_fori * stmt)531 free_fori(PLpgSQL_stmt_fori *stmt)
532 {
533 	free_expr(stmt->lower);
534 	free_expr(stmt->upper);
535 	free_expr(stmt->step);
536 	free_stmts(stmt->body);
537 }
538 
539 static void
free_fors(PLpgSQL_stmt_fors * stmt)540 free_fors(PLpgSQL_stmt_fors *stmt)
541 {
542 	free_stmts(stmt->body);
543 	free_expr(stmt->query);
544 }
545 
546 static void
free_forc(PLpgSQL_stmt_forc * stmt)547 free_forc(PLpgSQL_stmt_forc *stmt)
548 {
549 	free_stmts(stmt->body);
550 	free_expr(stmt->argquery);
551 }
552 
553 static void
free_foreach_a(PLpgSQL_stmt_foreach_a * stmt)554 free_foreach_a(PLpgSQL_stmt_foreach_a *stmt)
555 {
556 	free_expr(stmt->expr);
557 	free_stmts(stmt->body);
558 }
559 
560 static void
free_open(PLpgSQL_stmt_open * stmt)561 free_open(PLpgSQL_stmt_open *stmt)
562 {
563 	ListCell   *lc;
564 
565 	free_expr(stmt->argquery);
566 	free_expr(stmt->query);
567 	free_expr(stmt->dynquery);
568 	foreach(lc, stmt->params)
569 	{
570 		free_expr((PLpgSQL_expr *) lfirst(lc));
571 	}
572 }
573 
574 static void
free_fetch(PLpgSQL_stmt_fetch * stmt)575 free_fetch(PLpgSQL_stmt_fetch *stmt)
576 {
577 	free_expr(stmt->expr);
578 }
579 
580 static void
free_close(PLpgSQL_stmt_close * stmt)581 free_close(PLpgSQL_stmt_close *stmt)
582 {
583 }
584 
585 static void
free_perform(PLpgSQL_stmt_perform * stmt)586 free_perform(PLpgSQL_stmt_perform *stmt)
587 {
588 	free_expr(stmt->expr);
589 }
590 
591 static void
free_exit(PLpgSQL_stmt_exit * stmt)592 free_exit(PLpgSQL_stmt_exit *stmt)
593 {
594 	free_expr(stmt->cond);
595 }
596 
597 static void
free_return(PLpgSQL_stmt_return * stmt)598 free_return(PLpgSQL_stmt_return *stmt)
599 {
600 	free_expr(stmt->expr);
601 }
602 
603 static void
free_return_next(PLpgSQL_stmt_return_next * stmt)604 free_return_next(PLpgSQL_stmt_return_next *stmt)
605 {
606 	free_expr(stmt->expr);
607 }
608 
609 static void
free_return_query(PLpgSQL_stmt_return_query * stmt)610 free_return_query(PLpgSQL_stmt_return_query *stmt)
611 {
612 	ListCell   *lc;
613 
614 	free_expr(stmt->query);
615 	free_expr(stmt->dynquery);
616 	foreach(lc, stmt->params)
617 	{
618 		free_expr((PLpgSQL_expr *) lfirst(lc));
619 	}
620 }
621 
622 static void
free_raise(PLpgSQL_stmt_raise * stmt)623 free_raise(PLpgSQL_stmt_raise *stmt)
624 {
625 	ListCell   *lc;
626 
627 	foreach(lc, stmt->params)
628 	{
629 		free_expr((PLpgSQL_expr *) lfirst(lc));
630 	}
631 	foreach(lc, stmt->options)
632 	{
633 		PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
634 
635 		free_expr(opt->expr);
636 	}
637 }
638 
639 static void
free_assert(PLpgSQL_stmt_assert * stmt)640 free_assert(PLpgSQL_stmt_assert *stmt)
641 {
642 	free_expr(stmt->cond);
643 	free_expr(stmt->message);
644 }
645 
646 static void
free_execsql(PLpgSQL_stmt_execsql * stmt)647 free_execsql(PLpgSQL_stmt_execsql *stmt)
648 {
649 	free_expr(stmt->sqlstmt);
650 }
651 
652 static void
free_dynexecute(PLpgSQL_stmt_dynexecute * stmt)653 free_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
654 {
655 	ListCell   *lc;
656 
657 	free_expr(stmt->query);
658 	foreach(lc, stmt->params)
659 	{
660 		free_expr((PLpgSQL_expr *) lfirst(lc));
661 	}
662 }
663 
664 static void
free_dynfors(PLpgSQL_stmt_dynfors * stmt)665 free_dynfors(PLpgSQL_stmt_dynfors *stmt)
666 {
667 	ListCell   *lc;
668 
669 	free_stmts(stmt->body);
670 	free_expr(stmt->query);
671 	foreach(lc, stmt->params)
672 	{
673 		free_expr((PLpgSQL_expr *) lfirst(lc));
674 	}
675 }
676 
677 static void
free_getdiag(PLpgSQL_stmt_getdiag * stmt)678 free_getdiag(PLpgSQL_stmt_getdiag *stmt)
679 {
680 }
681 
682 static void
free_expr(PLpgSQL_expr * expr)683 free_expr(PLpgSQL_expr *expr)
684 {
685 	if (expr && expr->plan)
686 	{
687 		SPI_freeplan(expr->plan);
688 		expr->plan = NULL;
689 	}
690 }
691 
692 void
plpgsql_free_function_memory(PLpgSQL_function * func)693 plpgsql_free_function_memory(PLpgSQL_function *func)
694 {
695 	int			i;
696 
697 	/* Better not call this on an in-use function */
698 	Assert(func->use_count == 0);
699 
700 	/* Release plans associated with variable declarations */
701 	for (i = 0; i < func->ndatums; i++)
702 	{
703 		PLpgSQL_datum *d = func->datums[i];
704 
705 		switch (d->dtype)
706 		{
707 			case PLPGSQL_DTYPE_VAR:
708 				{
709 					PLpgSQL_var *var = (PLpgSQL_var *) d;
710 
711 					free_expr(var->default_val);
712 					free_expr(var->cursor_explicit_expr);
713 				}
714 				break;
715 			case PLPGSQL_DTYPE_ROW:
716 				break;
717 			case PLPGSQL_DTYPE_REC:
718 				break;
719 			case PLPGSQL_DTYPE_RECFIELD:
720 				break;
721 			case PLPGSQL_DTYPE_ARRAYELEM:
722 				free_expr(((PLpgSQL_arrayelem *) d)->subscript);
723 				break;
724 			default:
725 				elog(ERROR, "unrecognized data type: %d", d->dtype);
726 		}
727 	}
728 	func->ndatums = 0;
729 
730 	/* Release plans in statement tree */
731 	if (func->action)
732 		free_block(func->action);
733 	func->action = NULL;
734 
735 	/*
736 	 * And finally, release all memory except the PLpgSQL_function struct
737 	 * itself (which has to be kept around because there may be multiple
738 	 * fn_extra pointers to it).
739 	 */
740 	if (func->fn_cxt)
741 		MemoryContextDelete(func->fn_cxt);
742 	func->fn_cxt = NULL;
743 }
744 
745 
746 /**********************************************************************
747  * Debug functions for analyzing the compiled code
748  **********************************************************************/
749 static int	dump_indent;
750 
751 static void dump_ind(void);
752 static void dump_stmt(PLpgSQL_stmt *stmt);
753 static void dump_block(PLpgSQL_stmt_block *block);
754 static void dump_assign(PLpgSQL_stmt_assign *stmt);
755 static void dump_if(PLpgSQL_stmt_if *stmt);
756 static void dump_case(PLpgSQL_stmt_case *stmt);
757 static void dump_loop(PLpgSQL_stmt_loop *stmt);
758 static void dump_while(PLpgSQL_stmt_while *stmt);
759 static void dump_fori(PLpgSQL_stmt_fori *stmt);
760 static void dump_fors(PLpgSQL_stmt_fors *stmt);
761 static void dump_forc(PLpgSQL_stmt_forc *stmt);
762 static void dump_foreach_a(PLpgSQL_stmt_foreach_a *stmt);
763 static void dump_exit(PLpgSQL_stmt_exit *stmt);
764 static void dump_return(PLpgSQL_stmt_return *stmt);
765 static void dump_return_next(PLpgSQL_stmt_return_next *stmt);
766 static void dump_return_query(PLpgSQL_stmt_return_query *stmt);
767 static void dump_raise(PLpgSQL_stmt_raise *stmt);
768 static void dump_assert(PLpgSQL_stmt_assert *stmt);
769 static void dump_execsql(PLpgSQL_stmt_execsql *stmt);
770 static void dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
771 static void dump_dynfors(PLpgSQL_stmt_dynfors *stmt);
772 static void dump_getdiag(PLpgSQL_stmt_getdiag *stmt);
773 static void dump_open(PLpgSQL_stmt_open *stmt);
774 static void dump_fetch(PLpgSQL_stmt_fetch *stmt);
775 static void dump_cursor_direction(PLpgSQL_stmt_fetch *stmt);
776 static void dump_close(PLpgSQL_stmt_close *stmt);
777 static void dump_perform(PLpgSQL_stmt_perform *stmt);
778 static void dump_expr(PLpgSQL_expr *expr);
779 
780 
781 static void
dump_ind(void)782 dump_ind(void)
783 {
784 	int			i;
785 
786 	for (i = 0; i < dump_indent; i++)
787 		printf(" ");
788 }
789 
790 static void
dump_stmt(PLpgSQL_stmt * stmt)791 dump_stmt(PLpgSQL_stmt *stmt)
792 {
793 	printf("%3d:", stmt->lineno);
794 	switch ((enum PLpgSQL_stmt_types) stmt->cmd_type)
795 	{
796 		case PLPGSQL_STMT_BLOCK:
797 			dump_block((PLpgSQL_stmt_block *) stmt);
798 			break;
799 		case PLPGSQL_STMT_ASSIGN:
800 			dump_assign((PLpgSQL_stmt_assign *) stmt);
801 			break;
802 		case PLPGSQL_STMT_IF:
803 			dump_if((PLpgSQL_stmt_if *) stmt);
804 			break;
805 		case PLPGSQL_STMT_CASE:
806 			dump_case((PLpgSQL_stmt_case *) stmt);
807 			break;
808 		case PLPGSQL_STMT_LOOP:
809 			dump_loop((PLpgSQL_stmt_loop *) stmt);
810 			break;
811 		case PLPGSQL_STMT_WHILE:
812 			dump_while((PLpgSQL_stmt_while *) stmt);
813 			break;
814 		case PLPGSQL_STMT_FORI:
815 			dump_fori((PLpgSQL_stmt_fori *) stmt);
816 			break;
817 		case PLPGSQL_STMT_FORS:
818 			dump_fors((PLpgSQL_stmt_fors *) stmt);
819 			break;
820 		case PLPGSQL_STMT_FORC:
821 			dump_forc((PLpgSQL_stmt_forc *) stmt);
822 			break;
823 		case PLPGSQL_STMT_FOREACH_A:
824 			dump_foreach_a((PLpgSQL_stmt_foreach_a *) stmt);
825 			break;
826 		case PLPGSQL_STMT_EXIT:
827 			dump_exit((PLpgSQL_stmt_exit *) stmt);
828 			break;
829 		case PLPGSQL_STMT_RETURN:
830 			dump_return((PLpgSQL_stmt_return *) stmt);
831 			break;
832 		case PLPGSQL_STMT_RETURN_NEXT:
833 			dump_return_next((PLpgSQL_stmt_return_next *) stmt);
834 			break;
835 		case PLPGSQL_STMT_RETURN_QUERY:
836 			dump_return_query((PLpgSQL_stmt_return_query *) stmt);
837 			break;
838 		case PLPGSQL_STMT_RAISE:
839 			dump_raise((PLpgSQL_stmt_raise *) stmt);
840 			break;
841 		case PLPGSQL_STMT_ASSERT:
842 			dump_assert((PLpgSQL_stmt_assert *) stmt);
843 			break;
844 		case PLPGSQL_STMT_EXECSQL:
845 			dump_execsql((PLpgSQL_stmt_execsql *) stmt);
846 			break;
847 		case PLPGSQL_STMT_DYNEXECUTE:
848 			dump_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
849 			break;
850 		case PLPGSQL_STMT_DYNFORS:
851 			dump_dynfors((PLpgSQL_stmt_dynfors *) stmt);
852 			break;
853 		case PLPGSQL_STMT_GETDIAG:
854 			dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
855 			break;
856 		case PLPGSQL_STMT_OPEN:
857 			dump_open((PLpgSQL_stmt_open *) stmt);
858 			break;
859 		case PLPGSQL_STMT_FETCH:
860 			dump_fetch((PLpgSQL_stmt_fetch *) stmt);
861 			break;
862 		case PLPGSQL_STMT_CLOSE:
863 			dump_close((PLpgSQL_stmt_close *) stmt);
864 			break;
865 		case PLPGSQL_STMT_PERFORM:
866 			dump_perform((PLpgSQL_stmt_perform *) stmt);
867 			break;
868 		default:
869 			elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
870 			break;
871 	}
872 }
873 
874 static void
dump_stmts(List * stmts)875 dump_stmts(List *stmts)
876 {
877 	ListCell   *s;
878 
879 	dump_indent += 2;
880 	foreach(s, stmts)
881 		dump_stmt((PLpgSQL_stmt *) lfirst(s));
882 	dump_indent -= 2;
883 }
884 
885 static void
dump_block(PLpgSQL_stmt_block * block)886 dump_block(PLpgSQL_stmt_block *block)
887 {
888 	char	   *name;
889 
890 	if (block->label == NULL)
891 		name = "*unnamed*";
892 	else
893 		name = block->label;
894 
895 	dump_ind();
896 	printf("BLOCK <<%s>>\n", name);
897 
898 	dump_stmts(block->body);
899 
900 	if (block->exceptions)
901 	{
902 		ListCell   *e;
903 
904 		foreach(e, block->exceptions->exc_list)
905 		{
906 			PLpgSQL_exception *exc = (PLpgSQL_exception *) lfirst(e);
907 			PLpgSQL_condition *cond;
908 
909 			dump_ind();
910 			printf("    EXCEPTION WHEN ");
911 			for (cond = exc->conditions; cond; cond = cond->next)
912 			{
913 				if (cond != exc->conditions)
914 					printf(" OR ");
915 				printf("%s", cond->condname);
916 			}
917 			printf(" THEN\n");
918 			dump_stmts(exc->action);
919 		}
920 	}
921 
922 	dump_ind();
923 	printf("    END -- %s\n", name);
924 }
925 
926 static void
dump_assign(PLpgSQL_stmt_assign * stmt)927 dump_assign(PLpgSQL_stmt_assign *stmt)
928 {
929 	dump_ind();
930 	printf("ASSIGN var %d := ", stmt->varno);
931 	dump_expr(stmt->expr);
932 	printf("\n");
933 }
934 
935 static void
dump_if(PLpgSQL_stmt_if * stmt)936 dump_if(PLpgSQL_stmt_if *stmt)
937 {
938 	ListCell   *l;
939 
940 	dump_ind();
941 	printf("IF ");
942 	dump_expr(stmt->cond);
943 	printf(" THEN\n");
944 	dump_stmts(stmt->then_body);
945 	foreach(l, stmt->elsif_list)
946 	{
947 		PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(l);
948 
949 		dump_ind();
950 		printf("    ELSIF ");
951 		dump_expr(elif->cond);
952 		printf(" THEN\n");
953 		dump_stmts(elif->stmts);
954 	}
955 	if (stmt->else_body != NIL)
956 	{
957 		dump_ind();
958 		printf("    ELSE\n");
959 		dump_stmts(stmt->else_body);
960 	}
961 	dump_ind();
962 	printf("    ENDIF\n");
963 }
964 
965 static void
dump_case(PLpgSQL_stmt_case * stmt)966 dump_case(PLpgSQL_stmt_case *stmt)
967 {
968 	ListCell   *l;
969 
970 	dump_ind();
971 	printf("CASE %d ", stmt->t_varno);
972 	if (stmt->t_expr)
973 		dump_expr(stmt->t_expr);
974 	printf("\n");
975 	dump_indent += 6;
976 	foreach(l, stmt->case_when_list)
977 	{
978 		PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
979 
980 		dump_ind();
981 		printf("WHEN ");
982 		dump_expr(cwt->expr);
983 		printf("\n");
984 		dump_ind();
985 		printf("THEN\n");
986 		dump_indent += 2;
987 		dump_stmts(cwt->stmts);
988 		dump_indent -= 2;
989 	}
990 	if (stmt->have_else)
991 	{
992 		dump_ind();
993 		printf("ELSE\n");
994 		dump_indent += 2;
995 		dump_stmts(stmt->else_stmts);
996 		dump_indent -= 2;
997 	}
998 	dump_indent -= 6;
999 	dump_ind();
1000 	printf("    ENDCASE\n");
1001 }
1002 
1003 static void
dump_loop(PLpgSQL_stmt_loop * stmt)1004 dump_loop(PLpgSQL_stmt_loop *stmt)
1005 {
1006 	dump_ind();
1007 	printf("LOOP\n");
1008 
1009 	dump_stmts(stmt->body);
1010 
1011 	dump_ind();
1012 	printf("    ENDLOOP\n");
1013 }
1014 
1015 static void
dump_while(PLpgSQL_stmt_while * stmt)1016 dump_while(PLpgSQL_stmt_while *stmt)
1017 {
1018 	dump_ind();
1019 	printf("WHILE ");
1020 	dump_expr(stmt->cond);
1021 	printf("\n");
1022 
1023 	dump_stmts(stmt->body);
1024 
1025 	dump_ind();
1026 	printf("    ENDWHILE\n");
1027 }
1028 
1029 static void
dump_fori(PLpgSQL_stmt_fori * stmt)1030 dump_fori(PLpgSQL_stmt_fori *stmt)
1031 {
1032 	dump_ind();
1033 	printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
1034 
1035 	dump_indent += 2;
1036 	dump_ind();
1037 	printf("    lower = ");
1038 	dump_expr(stmt->lower);
1039 	printf("\n");
1040 	dump_ind();
1041 	printf("    upper = ");
1042 	dump_expr(stmt->upper);
1043 	printf("\n");
1044 	if (stmt->step)
1045 	{
1046 		dump_ind();
1047 		printf("    step = ");
1048 		dump_expr(stmt->step);
1049 		printf("\n");
1050 	}
1051 	dump_indent -= 2;
1052 
1053 	dump_stmts(stmt->body);
1054 
1055 	dump_ind();
1056 	printf("    ENDFORI\n");
1057 }
1058 
1059 static void
dump_fors(PLpgSQL_stmt_fors * stmt)1060 dump_fors(PLpgSQL_stmt_fors *stmt)
1061 {
1062 	dump_ind();
1063 	printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
1064 	dump_expr(stmt->query);
1065 	printf("\n");
1066 
1067 	dump_stmts(stmt->body);
1068 
1069 	dump_ind();
1070 	printf("    ENDFORS\n");
1071 }
1072 
1073 static void
dump_forc(PLpgSQL_stmt_forc * stmt)1074 dump_forc(PLpgSQL_stmt_forc *stmt)
1075 {
1076 	dump_ind();
1077 	printf("FORC %s ", stmt->rec->refname);
1078 	printf("curvar=%d\n", stmt->curvar);
1079 
1080 	dump_indent += 2;
1081 	if (stmt->argquery != NULL)
1082 	{
1083 		dump_ind();
1084 		printf("  arguments = ");
1085 		dump_expr(stmt->argquery);
1086 		printf("\n");
1087 	}
1088 	dump_indent -= 2;
1089 
1090 	dump_stmts(stmt->body);
1091 
1092 	dump_ind();
1093 	printf("    ENDFORC\n");
1094 }
1095 
1096 static void
dump_foreach_a(PLpgSQL_stmt_foreach_a * stmt)1097 dump_foreach_a(PLpgSQL_stmt_foreach_a *stmt)
1098 {
1099 	dump_ind();
1100 	printf("FOREACHA var %d ", stmt->varno);
1101 	if (stmt->slice != 0)
1102 		printf("SLICE %d ", stmt->slice);
1103 	printf("IN ");
1104 	dump_expr(stmt->expr);
1105 	printf("\n");
1106 
1107 	dump_stmts(stmt->body);
1108 
1109 	dump_ind();
1110 	printf("    ENDFOREACHA");
1111 }
1112 
1113 static void
dump_open(PLpgSQL_stmt_open * stmt)1114 dump_open(PLpgSQL_stmt_open *stmt)
1115 {
1116 	dump_ind();
1117 	printf("OPEN curvar=%d\n", stmt->curvar);
1118 
1119 	dump_indent += 2;
1120 	if (stmt->argquery != NULL)
1121 	{
1122 		dump_ind();
1123 		printf("  arguments = '");
1124 		dump_expr(stmt->argquery);
1125 		printf("'\n");
1126 	}
1127 	if (stmt->query != NULL)
1128 	{
1129 		dump_ind();
1130 		printf("  query = '");
1131 		dump_expr(stmt->query);
1132 		printf("'\n");
1133 	}
1134 	if (stmt->dynquery != NULL)
1135 	{
1136 		dump_ind();
1137 		printf("  execute = '");
1138 		dump_expr(stmt->dynquery);
1139 		printf("'\n");
1140 
1141 		if (stmt->params != NIL)
1142 		{
1143 			ListCell   *lc;
1144 			int			i;
1145 
1146 			dump_indent += 2;
1147 			dump_ind();
1148 			printf("    USING\n");
1149 			dump_indent += 2;
1150 			i = 1;
1151 			foreach(lc, stmt->params)
1152 			{
1153 				dump_ind();
1154 				printf("    parameter $%d: ", i++);
1155 				dump_expr((PLpgSQL_expr *) lfirst(lc));
1156 				printf("\n");
1157 			}
1158 			dump_indent -= 4;
1159 		}
1160 	}
1161 	dump_indent -= 2;
1162 }
1163 
1164 static void
dump_fetch(PLpgSQL_stmt_fetch * stmt)1165 dump_fetch(PLpgSQL_stmt_fetch *stmt)
1166 {
1167 	dump_ind();
1168 
1169 	if (!stmt->is_move)
1170 	{
1171 		printf("FETCH curvar=%d\n", stmt->curvar);
1172 		dump_cursor_direction(stmt);
1173 
1174 		dump_indent += 2;
1175 		if (stmt->rec != NULL)
1176 		{
1177 			dump_ind();
1178 			printf("    target = %d %s\n", stmt->rec->dno, stmt->rec->refname);
1179 		}
1180 		if (stmt->row != NULL)
1181 		{
1182 			dump_ind();
1183 			printf("    target = %d %s\n", stmt->row->dno, stmt->row->refname);
1184 		}
1185 		dump_indent -= 2;
1186 	}
1187 	else
1188 	{
1189 		printf("MOVE curvar=%d\n", stmt->curvar);
1190 		dump_cursor_direction(stmt);
1191 	}
1192 }
1193 
1194 static void
dump_cursor_direction(PLpgSQL_stmt_fetch * stmt)1195 dump_cursor_direction(PLpgSQL_stmt_fetch *stmt)
1196 {
1197 	dump_indent += 2;
1198 	dump_ind();
1199 	switch (stmt->direction)
1200 	{
1201 		case FETCH_FORWARD:
1202 			printf("    FORWARD ");
1203 			break;
1204 		case FETCH_BACKWARD:
1205 			printf("    BACKWARD ");
1206 			break;
1207 		case FETCH_ABSOLUTE:
1208 			printf("    ABSOLUTE ");
1209 			break;
1210 		case FETCH_RELATIVE:
1211 			printf("    RELATIVE ");
1212 			break;
1213 		default:
1214 			printf("??? unknown cursor direction %d", stmt->direction);
1215 	}
1216 
1217 	if (stmt->expr)
1218 	{
1219 		dump_expr(stmt->expr);
1220 		printf("\n");
1221 	}
1222 	else
1223 		printf("%ld\n", stmt->how_many);
1224 
1225 	dump_indent -= 2;
1226 }
1227 
1228 static void
dump_close(PLpgSQL_stmt_close * stmt)1229 dump_close(PLpgSQL_stmt_close *stmt)
1230 {
1231 	dump_ind();
1232 	printf("CLOSE curvar=%d\n", stmt->curvar);
1233 }
1234 
1235 static void
dump_perform(PLpgSQL_stmt_perform * stmt)1236 dump_perform(PLpgSQL_stmt_perform *stmt)
1237 {
1238 	dump_ind();
1239 	printf("PERFORM expr = ");
1240 	dump_expr(stmt->expr);
1241 	printf("\n");
1242 }
1243 
1244 static void
dump_exit(PLpgSQL_stmt_exit * stmt)1245 dump_exit(PLpgSQL_stmt_exit *stmt)
1246 {
1247 	dump_ind();
1248 	printf("%s", stmt->is_exit ? "EXIT" : "CONTINUE");
1249 	if (stmt->label != NULL)
1250 		printf(" label='%s'", stmt->label);
1251 	if (stmt->cond != NULL)
1252 	{
1253 		printf(" WHEN ");
1254 		dump_expr(stmt->cond);
1255 	}
1256 	printf("\n");
1257 }
1258 
1259 static void
dump_return(PLpgSQL_stmt_return * stmt)1260 dump_return(PLpgSQL_stmt_return *stmt)
1261 {
1262 	dump_ind();
1263 	printf("RETURN ");
1264 	if (stmt->retvarno >= 0)
1265 		printf("variable %d", stmt->retvarno);
1266 	else if (stmt->expr != NULL)
1267 		dump_expr(stmt->expr);
1268 	else
1269 		printf("NULL");
1270 	printf("\n");
1271 }
1272 
1273 static void
dump_return_next(PLpgSQL_stmt_return_next * stmt)1274 dump_return_next(PLpgSQL_stmt_return_next *stmt)
1275 {
1276 	dump_ind();
1277 	printf("RETURN NEXT ");
1278 	if (stmt->retvarno >= 0)
1279 		printf("variable %d", stmt->retvarno);
1280 	else if (stmt->expr != NULL)
1281 		dump_expr(stmt->expr);
1282 	else
1283 		printf("NULL");
1284 	printf("\n");
1285 }
1286 
1287 static void
dump_return_query(PLpgSQL_stmt_return_query * stmt)1288 dump_return_query(PLpgSQL_stmt_return_query *stmt)
1289 {
1290 	dump_ind();
1291 	if (stmt->query)
1292 	{
1293 		printf("RETURN QUERY ");
1294 		dump_expr(stmt->query);
1295 		printf("\n");
1296 	}
1297 	else
1298 	{
1299 		printf("RETURN QUERY EXECUTE ");
1300 		dump_expr(stmt->dynquery);
1301 		printf("\n");
1302 		if (stmt->params != NIL)
1303 		{
1304 			ListCell   *lc;
1305 			int			i;
1306 
1307 			dump_indent += 2;
1308 			dump_ind();
1309 			printf("    USING\n");
1310 			dump_indent += 2;
1311 			i = 1;
1312 			foreach(lc, stmt->params)
1313 			{
1314 				dump_ind();
1315 				printf("    parameter $%d: ", i++);
1316 				dump_expr((PLpgSQL_expr *) lfirst(lc));
1317 				printf("\n");
1318 			}
1319 			dump_indent -= 4;
1320 		}
1321 	}
1322 }
1323 
1324 static void
dump_raise(PLpgSQL_stmt_raise * stmt)1325 dump_raise(PLpgSQL_stmt_raise *stmt)
1326 {
1327 	ListCell   *lc;
1328 	int			i = 0;
1329 
1330 	dump_ind();
1331 	printf("RAISE level=%d", stmt->elog_level);
1332 	if (stmt->condname)
1333 		printf(" condname='%s'", stmt->condname);
1334 	if (stmt->message)
1335 		printf(" message='%s'", stmt->message);
1336 	printf("\n");
1337 	dump_indent += 2;
1338 	foreach(lc, stmt->params)
1339 	{
1340 		dump_ind();
1341 		printf("    parameter %d: ", i++);
1342 		dump_expr((PLpgSQL_expr *) lfirst(lc));
1343 		printf("\n");
1344 	}
1345 	if (stmt->options)
1346 	{
1347 		dump_ind();
1348 		printf("    USING\n");
1349 		dump_indent += 2;
1350 		foreach(lc, stmt->options)
1351 		{
1352 			PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
1353 
1354 			dump_ind();
1355 			switch (opt->opt_type)
1356 			{
1357 				case PLPGSQL_RAISEOPTION_ERRCODE:
1358 					printf("    ERRCODE = ");
1359 					break;
1360 				case PLPGSQL_RAISEOPTION_MESSAGE:
1361 					printf("    MESSAGE = ");
1362 					break;
1363 				case PLPGSQL_RAISEOPTION_DETAIL:
1364 					printf("    DETAIL = ");
1365 					break;
1366 				case PLPGSQL_RAISEOPTION_HINT:
1367 					printf("    HINT = ");
1368 					break;
1369 				case PLPGSQL_RAISEOPTION_COLUMN:
1370 					printf("    COLUMN = ");
1371 					break;
1372 				case PLPGSQL_RAISEOPTION_CONSTRAINT:
1373 					printf("    CONSTRAINT = ");
1374 					break;
1375 				case PLPGSQL_RAISEOPTION_DATATYPE:
1376 					printf("    DATATYPE = ");
1377 					break;
1378 				case PLPGSQL_RAISEOPTION_TABLE:
1379 					printf("    TABLE = ");
1380 					break;
1381 				case PLPGSQL_RAISEOPTION_SCHEMA:
1382 					printf("    SCHEMA = ");
1383 					break;
1384 			}
1385 			dump_expr(opt->expr);
1386 			printf("\n");
1387 		}
1388 		dump_indent -= 2;
1389 	}
1390 	dump_indent -= 2;
1391 }
1392 
1393 static void
dump_assert(PLpgSQL_stmt_assert * stmt)1394 dump_assert(PLpgSQL_stmt_assert *stmt)
1395 {
1396 	dump_ind();
1397 	printf("ASSERT ");
1398 	dump_expr(stmt->cond);
1399 	printf("\n");
1400 
1401 	dump_indent += 2;
1402 	if (stmt->message != NULL)
1403 	{
1404 		dump_ind();
1405 		printf("    MESSAGE = ");
1406 		dump_expr(stmt->message);
1407 		printf("\n");
1408 	}
1409 	dump_indent -= 2;
1410 }
1411 
1412 static void
dump_execsql(PLpgSQL_stmt_execsql * stmt)1413 dump_execsql(PLpgSQL_stmt_execsql *stmt)
1414 {
1415 	dump_ind();
1416 	printf("EXECSQL ");
1417 	dump_expr(stmt->sqlstmt);
1418 	printf("\n");
1419 
1420 	dump_indent += 2;
1421 	if (stmt->rec != NULL)
1422 	{
1423 		dump_ind();
1424 		printf("    INTO%s target = %d %s\n",
1425 			   stmt->strict ? " STRICT" : "",
1426 			   stmt->rec->dno, stmt->rec->refname);
1427 	}
1428 	if (stmt->row != NULL)
1429 	{
1430 		dump_ind();
1431 		printf("    INTO%s target = %d %s\n",
1432 			   stmt->strict ? " STRICT" : "",
1433 			   stmt->row->dno, stmt->row->refname);
1434 	}
1435 	dump_indent -= 2;
1436 }
1437 
1438 static void
dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt)1439 dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
1440 {
1441 	dump_ind();
1442 	printf("EXECUTE ");
1443 	dump_expr(stmt->query);
1444 	printf("\n");
1445 
1446 	dump_indent += 2;
1447 	if (stmt->rec != NULL)
1448 	{
1449 		dump_ind();
1450 		printf("    INTO%s target = %d %s\n",
1451 			   stmt->strict ? " STRICT" : "",
1452 			   stmt->rec->dno, stmt->rec->refname);
1453 	}
1454 	if (stmt->row != NULL)
1455 	{
1456 		dump_ind();
1457 		printf("    INTO%s target = %d %s\n",
1458 			   stmt->strict ? " STRICT" : "",
1459 			   stmt->row->dno, stmt->row->refname);
1460 	}
1461 	if (stmt->params != NIL)
1462 	{
1463 		ListCell   *lc;
1464 		int			i;
1465 
1466 		dump_ind();
1467 		printf("    USING\n");
1468 		dump_indent += 2;
1469 		i = 1;
1470 		foreach(lc, stmt->params)
1471 		{
1472 			dump_ind();
1473 			printf("    parameter %d: ", i++);
1474 			dump_expr((PLpgSQL_expr *) lfirst(lc));
1475 			printf("\n");
1476 		}
1477 		dump_indent -= 2;
1478 	}
1479 	dump_indent -= 2;
1480 }
1481 
1482 static void
dump_dynfors(PLpgSQL_stmt_dynfors * stmt)1483 dump_dynfors(PLpgSQL_stmt_dynfors *stmt)
1484 {
1485 	dump_ind();
1486 	printf("FORS %s EXECUTE ",
1487 		   (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
1488 	dump_expr(stmt->query);
1489 	printf("\n");
1490 	if (stmt->params != NIL)
1491 	{
1492 		ListCell   *lc;
1493 		int			i;
1494 
1495 		dump_indent += 2;
1496 		dump_ind();
1497 		printf("    USING\n");
1498 		dump_indent += 2;
1499 		i = 1;
1500 		foreach(lc, stmt->params)
1501 		{
1502 			dump_ind();
1503 			printf("    parameter $%d: ", i++);
1504 			dump_expr((PLpgSQL_expr *) lfirst(lc));
1505 			printf("\n");
1506 		}
1507 		dump_indent -= 4;
1508 	}
1509 	dump_stmts(stmt->body);
1510 	dump_ind();
1511 	printf("    ENDFORS\n");
1512 }
1513 
1514 static void
dump_getdiag(PLpgSQL_stmt_getdiag * stmt)1515 dump_getdiag(PLpgSQL_stmt_getdiag *stmt)
1516 {
1517 	ListCell   *lc;
1518 
1519 	dump_ind();
1520 	printf("GET %s DIAGNOSTICS ", stmt->is_stacked ? "STACKED" : "CURRENT");
1521 	foreach(lc, stmt->diag_items)
1522 	{
1523 		PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
1524 
1525 		if (lc != list_head(stmt->diag_items))
1526 			printf(", ");
1527 
1528 		printf("{var %d} = %s", diag_item->target,
1529 			   plpgsql_getdiag_kindname(diag_item->kind));
1530 	}
1531 	printf("\n");
1532 }
1533 
1534 static void
dump_expr(PLpgSQL_expr * expr)1535 dump_expr(PLpgSQL_expr *expr)
1536 {
1537 	printf("'%s'", expr->query);
1538 }
1539 
1540 void
plpgsql_dumptree(PLpgSQL_function * func)1541 plpgsql_dumptree(PLpgSQL_function *func)
1542 {
1543 	int			i;
1544 	PLpgSQL_datum *d;
1545 
1546 	printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
1547 		   func->fn_signature);
1548 
1549 	printf("\nFunction's data area:\n");
1550 	for (i = 0; i < func->ndatums; i++)
1551 	{
1552 		d = func->datums[i];
1553 
1554 		printf("    entry %d: ", i);
1555 		switch (d->dtype)
1556 		{
1557 			case PLPGSQL_DTYPE_VAR:
1558 				{
1559 					PLpgSQL_var *var = (PLpgSQL_var *) d;
1560 
1561 					printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
1562 						   var->refname, var->datatype->typname,
1563 						   var->datatype->typoid,
1564 						   var->datatype->atttypmod);
1565 					if (var->isconst)
1566 						printf("                                  CONSTANT\n");
1567 					if (var->notnull)
1568 						printf("                                  NOT NULL\n");
1569 					if (var->default_val != NULL)
1570 					{
1571 						printf("                                  DEFAULT ");
1572 						dump_expr(var->default_val);
1573 						printf("\n");
1574 					}
1575 					if (var->cursor_explicit_expr != NULL)
1576 					{
1577 						if (var->cursor_explicit_argrow >= 0)
1578 							printf("                                  CURSOR argument row %d\n", var->cursor_explicit_argrow);
1579 
1580 						printf("                                  CURSOR IS ");
1581 						dump_expr(var->cursor_explicit_expr);
1582 						printf("\n");
1583 					}
1584 				}
1585 				break;
1586 			case PLPGSQL_DTYPE_ROW:
1587 				{
1588 					PLpgSQL_row *row = (PLpgSQL_row *) d;
1589 					int			i;
1590 
1591 					printf("ROW %-16s fields", row->refname);
1592 					for (i = 0; i < row->nfields; i++)
1593 					{
1594 						if (row->fieldnames[i])
1595 							printf(" %s=var %d", row->fieldnames[i],
1596 								   row->varnos[i]);
1597 					}
1598 					printf("\n");
1599 				}
1600 				break;
1601 			case PLPGSQL_DTYPE_REC:
1602 				printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
1603 				break;
1604 			case PLPGSQL_DTYPE_RECFIELD:
1605 				printf("RECFIELD %-16s of REC %d\n",
1606 					   ((PLpgSQL_recfield *) d)->fieldname,
1607 					   ((PLpgSQL_recfield *) d)->recparentno);
1608 				break;
1609 			case PLPGSQL_DTYPE_ARRAYELEM:
1610 				printf("ARRAYELEM of VAR %d subscript ",
1611 					   ((PLpgSQL_arrayelem *) d)->arrayparentno);
1612 				dump_expr(((PLpgSQL_arrayelem *) d)->subscript);
1613 				printf("\n");
1614 				break;
1615 			default:
1616 				printf("??? unknown data type %d\n", d->dtype);
1617 		}
1618 	}
1619 	printf("\nFunction's statements:\n");
1620 
1621 	dump_indent = 0;
1622 	printf("%3d:", func->action->lineno);
1623 	dump_block(func->action);
1624 	printf("\nEnd of execution tree of function %s\n\n", func->fn_signature);
1625 	fflush(stdout);
1626 }
1627