1 /*-------------------------------------------------------------------------
2  *
3  * pl_funcs.c		- Misc functions for the PL/pgSQL
4  *			  procedural language
5  *
6  * Portions Copyright (c) 1996-2020, 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 "postgres.h"
17 
18 #include "plpgsql.h"
19 #include "utils/memutils.h"
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,PLpgSQL_label_type label_type)54 plpgsql_ns_push(const char *label, PLpgSQL_label_type 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(PLpgSQL_nsitem_type itemtype,int itemno,const char * name)92 plpgsql_ns_additem(PLpgSQL_nsitem_type 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 (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 		case PLPGSQL_STMT_CALL:
286 			return ((PLpgSQL_stmt_call *) stmt)->is_call ? "CALL" : "DO";
287 		case PLPGSQL_STMT_COMMIT:
288 			return "COMMIT";
289 		case PLPGSQL_STMT_ROLLBACK:
290 			return "ROLLBACK";
291 		case PLPGSQL_STMT_SET:
292 			return "SET";
293 	}
294 
295 	return "unknown";
296 }
297 
298 /*
299  * GET DIAGNOSTICS item name as a string, for use in error messages etc.
300  */
301 const char *
plpgsql_getdiag_kindname(PLpgSQL_getdiag_kind kind)302 plpgsql_getdiag_kindname(PLpgSQL_getdiag_kind kind)
303 {
304 	switch (kind)
305 	{
306 		case PLPGSQL_GETDIAG_ROW_COUNT:
307 			return "ROW_COUNT";
308 		case PLPGSQL_GETDIAG_CONTEXT:
309 			return "PG_CONTEXT";
310 		case PLPGSQL_GETDIAG_ERROR_CONTEXT:
311 			return "PG_EXCEPTION_CONTEXT";
312 		case PLPGSQL_GETDIAG_ERROR_DETAIL:
313 			return "PG_EXCEPTION_DETAIL";
314 		case PLPGSQL_GETDIAG_ERROR_HINT:
315 			return "PG_EXCEPTION_HINT";
316 		case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
317 			return "RETURNED_SQLSTATE";
318 		case PLPGSQL_GETDIAG_COLUMN_NAME:
319 			return "COLUMN_NAME";
320 		case PLPGSQL_GETDIAG_CONSTRAINT_NAME:
321 			return "CONSTRAINT_NAME";
322 		case PLPGSQL_GETDIAG_DATATYPE_NAME:
323 			return "PG_DATATYPE_NAME";
324 		case PLPGSQL_GETDIAG_MESSAGE_TEXT:
325 			return "MESSAGE_TEXT";
326 		case PLPGSQL_GETDIAG_TABLE_NAME:
327 			return "TABLE_NAME";
328 		case PLPGSQL_GETDIAG_SCHEMA_NAME:
329 			return "SCHEMA_NAME";
330 	}
331 
332 	return "unknown";
333 }
334 
335 
336 /**********************************************************************
337  * Release memory when a PL/pgSQL function is no longer needed
338  *
339  * The code for recursing through the function tree is really only
340  * needed to locate PLpgSQL_expr nodes, which may contain references
341  * to saved SPI Plans that must be freed.  The function tree itself,
342  * along with subsidiary data, is freed in one swoop by freeing the
343  * function's permanent memory context.
344  **********************************************************************/
345 static void free_stmt(PLpgSQL_stmt *stmt);
346 static void free_block(PLpgSQL_stmt_block *block);
347 static void free_assign(PLpgSQL_stmt_assign *stmt);
348 static void free_if(PLpgSQL_stmt_if *stmt);
349 static void free_case(PLpgSQL_stmt_case *stmt);
350 static void free_loop(PLpgSQL_stmt_loop *stmt);
351 static void free_while(PLpgSQL_stmt_while *stmt);
352 static void free_fori(PLpgSQL_stmt_fori *stmt);
353 static void free_fors(PLpgSQL_stmt_fors *stmt);
354 static void free_forc(PLpgSQL_stmt_forc *stmt);
355 static void free_foreach_a(PLpgSQL_stmt_foreach_a *stmt);
356 static void free_exit(PLpgSQL_stmt_exit *stmt);
357 static void free_return(PLpgSQL_stmt_return *stmt);
358 static void free_return_next(PLpgSQL_stmt_return_next *stmt);
359 static void free_return_query(PLpgSQL_stmt_return_query *stmt);
360 static void free_raise(PLpgSQL_stmt_raise *stmt);
361 static void free_assert(PLpgSQL_stmt_assert *stmt);
362 static void free_execsql(PLpgSQL_stmt_execsql *stmt);
363 static void free_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
364 static void free_dynfors(PLpgSQL_stmt_dynfors *stmt);
365 static void free_getdiag(PLpgSQL_stmt_getdiag *stmt);
366 static void free_open(PLpgSQL_stmt_open *stmt);
367 static void free_fetch(PLpgSQL_stmt_fetch *stmt);
368 static void free_close(PLpgSQL_stmt_close *stmt);
369 static void free_perform(PLpgSQL_stmt_perform *stmt);
370 static void free_call(PLpgSQL_stmt_call *stmt);
371 static void free_commit(PLpgSQL_stmt_commit *stmt);
372 static void free_rollback(PLpgSQL_stmt_rollback *stmt);
373 static void free_set(PLpgSQL_stmt_set *stmt);
374 static void free_expr(PLpgSQL_expr *expr);
375 
376 
377 static void
free_stmt(PLpgSQL_stmt * stmt)378 free_stmt(PLpgSQL_stmt *stmt)
379 {
380 	switch (stmt->cmd_type)
381 	{
382 		case PLPGSQL_STMT_BLOCK:
383 			free_block((PLpgSQL_stmt_block *) stmt);
384 			break;
385 		case PLPGSQL_STMT_ASSIGN:
386 			free_assign((PLpgSQL_stmt_assign *) stmt);
387 			break;
388 		case PLPGSQL_STMT_IF:
389 			free_if((PLpgSQL_stmt_if *) stmt);
390 			break;
391 		case PLPGSQL_STMT_CASE:
392 			free_case((PLpgSQL_stmt_case *) stmt);
393 			break;
394 		case PLPGSQL_STMT_LOOP:
395 			free_loop((PLpgSQL_stmt_loop *) stmt);
396 			break;
397 		case PLPGSQL_STMT_WHILE:
398 			free_while((PLpgSQL_stmt_while *) stmt);
399 			break;
400 		case PLPGSQL_STMT_FORI:
401 			free_fori((PLpgSQL_stmt_fori *) stmt);
402 			break;
403 		case PLPGSQL_STMT_FORS:
404 			free_fors((PLpgSQL_stmt_fors *) stmt);
405 			break;
406 		case PLPGSQL_STMT_FORC:
407 			free_forc((PLpgSQL_stmt_forc *) stmt);
408 			break;
409 		case PLPGSQL_STMT_FOREACH_A:
410 			free_foreach_a((PLpgSQL_stmt_foreach_a *) stmt);
411 			break;
412 		case PLPGSQL_STMT_EXIT:
413 			free_exit((PLpgSQL_stmt_exit *) stmt);
414 			break;
415 		case PLPGSQL_STMT_RETURN:
416 			free_return((PLpgSQL_stmt_return *) stmt);
417 			break;
418 		case PLPGSQL_STMT_RETURN_NEXT:
419 			free_return_next((PLpgSQL_stmt_return_next *) stmt);
420 			break;
421 		case PLPGSQL_STMT_RETURN_QUERY:
422 			free_return_query((PLpgSQL_stmt_return_query *) stmt);
423 			break;
424 		case PLPGSQL_STMT_RAISE:
425 			free_raise((PLpgSQL_stmt_raise *) stmt);
426 			break;
427 		case PLPGSQL_STMT_ASSERT:
428 			free_assert((PLpgSQL_stmt_assert *) stmt);
429 			break;
430 		case PLPGSQL_STMT_EXECSQL:
431 			free_execsql((PLpgSQL_stmt_execsql *) stmt);
432 			break;
433 		case PLPGSQL_STMT_DYNEXECUTE:
434 			free_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
435 			break;
436 		case PLPGSQL_STMT_DYNFORS:
437 			free_dynfors((PLpgSQL_stmt_dynfors *) stmt);
438 			break;
439 		case PLPGSQL_STMT_GETDIAG:
440 			free_getdiag((PLpgSQL_stmt_getdiag *) stmt);
441 			break;
442 		case PLPGSQL_STMT_OPEN:
443 			free_open((PLpgSQL_stmt_open *) stmt);
444 			break;
445 		case PLPGSQL_STMT_FETCH:
446 			free_fetch((PLpgSQL_stmt_fetch *) stmt);
447 			break;
448 		case PLPGSQL_STMT_CLOSE:
449 			free_close((PLpgSQL_stmt_close *) stmt);
450 			break;
451 		case PLPGSQL_STMT_PERFORM:
452 			free_perform((PLpgSQL_stmt_perform *) stmt);
453 			break;
454 		case PLPGSQL_STMT_CALL:
455 			free_call((PLpgSQL_stmt_call *) stmt);
456 			break;
457 		case PLPGSQL_STMT_COMMIT:
458 			free_commit((PLpgSQL_stmt_commit *) stmt);
459 			break;
460 		case PLPGSQL_STMT_ROLLBACK:
461 			free_rollback((PLpgSQL_stmt_rollback *) stmt);
462 			break;
463 		case PLPGSQL_STMT_SET:
464 			free_set((PLpgSQL_stmt_set *) stmt);
465 			break;
466 		default:
467 			elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
468 			break;
469 	}
470 }
471 
472 static void
free_stmts(List * stmts)473 free_stmts(List *stmts)
474 {
475 	ListCell   *s;
476 
477 	foreach(s, stmts)
478 	{
479 		free_stmt((PLpgSQL_stmt *) lfirst(s));
480 	}
481 }
482 
483 static void
free_block(PLpgSQL_stmt_block * block)484 free_block(PLpgSQL_stmt_block *block)
485 {
486 	free_stmts(block->body);
487 	if (block->exceptions)
488 	{
489 		ListCell   *e;
490 
491 		foreach(e, block->exceptions->exc_list)
492 		{
493 			PLpgSQL_exception *exc = (PLpgSQL_exception *) lfirst(e);
494 
495 			free_stmts(exc->action);
496 		}
497 	}
498 }
499 
500 static void
free_assign(PLpgSQL_stmt_assign * stmt)501 free_assign(PLpgSQL_stmt_assign *stmt)
502 {
503 	free_expr(stmt->expr);
504 }
505 
506 static void
free_if(PLpgSQL_stmt_if * stmt)507 free_if(PLpgSQL_stmt_if *stmt)
508 {
509 	ListCell   *l;
510 
511 	free_expr(stmt->cond);
512 	free_stmts(stmt->then_body);
513 	foreach(l, stmt->elsif_list)
514 	{
515 		PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(l);
516 
517 		free_expr(elif->cond);
518 		free_stmts(elif->stmts);
519 	}
520 	free_stmts(stmt->else_body);
521 }
522 
523 static void
free_case(PLpgSQL_stmt_case * stmt)524 free_case(PLpgSQL_stmt_case *stmt)
525 {
526 	ListCell   *l;
527 
528 	free_expr(stmt->t_expr);
529 	foreach(l, stmt->case_when_list)
530 	{
531 		PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
532 
533 		free_expr(cwt->expr);
534 		free_stmts(cwt->stmts);
535 	}
536 	free_stmts(stmt->else_stmts);
537 }
538 
539 static void
free_loop(PLpgSQL_stmt_loop * stmt)540 free_loop(PLpgSQL_stmt_loop *stmt)
541 {
542 	free_stmts(stmt->body);
543 }
544 
545 static void
free_while(PLpgSQL_stmt_while * stmt)546 free_while(PLpgSQL_stmt_while *stmt)
547 {
548 	free_expr(stmt->cond);
549 	free_stmts(stmt->body);
550 }
551 
552 static void
free_fori(PLpgSQL_stmt_fori * stmt)553 free_fori(PLpgSQL_stmt_fori *stmt)
554 {
555 	free_expr(stmt->lower);
556 	free_expr(stmt->upper);
557 	free_expr(stmt->step);
558 	free_stmts(stmt->body);
559 }
560 
561 static void
free_fors(PLpgSQL_stmt_fors * stmt)562 free_fors(PLpgSQL_stmt_fors *stmt)
563 {
564 	free_stmts(stmt->body);
565 	free_expr(stmt->query);
566 }
567 
568 static void
free_forc(PLpgSQL_stmt_forc * stmt)569 free_forc(PLpgSQL_stmt_forc *stmt)
570 {
571 	free_stmts(stmt->body);
572 	free_expr(stmt->argquery);
573 }
574 
575 static void
free_foreach_a(PLpgSQL_stmt_foreach_a * stmt)576 free_foreach_a(PLpgSQL_stmt_foreach_a *stmt)
577 {
578 	free_expr(stmt->expr);
579 	free_stmts(stmt->body);
580 }
581 
582 static void
free_open(PLpgSQL_stmt_open * stmt)583 free_open(PLpgSQL_stmt_open *stmt)
584 {
585 	ListCell   *lc;
586 
587 	free_expr(stmt->argquery);
588 	free_expr(stmt->query);
589 	free_expr(stmt->dynquery);
590 	foreach(lc, stmt->params)
591 	{
592 		free_expr((PLpgSQL_expr *) lfirst(lc));
593 	}
594 }
595 
596 static void
free_fetch(PLpgSQL_stmt_fetch * stmt)597 free_fetch(PLpgSQL_stmt_fetch *stmt)
598 {
599 	free_expr(stmt->expr);
600 }
601 
602 static void
free_close(PLpgSQL_stmt_close * stmt)603 free_close(PLpgSQL_stmt_close *stmt)
604 {
605 }
606 
607 static void
free_perform(PLpgSQL_stmt_perform * stmt)608 free_perform(PLpgSQL_stmt_perform *stmt)
609 {
610 	free_expr(stmt->expr);
611 }
612 
613 static void
free_call(PLpgSQL_stmt_call * stmt)614 free_call(PLpgSQL_stmt_call *stmt)
615 {
616 	free_expr(stmt->expr);
617 }
618 
619 static void
free_commit(PLpgSQL_stmt_commit * stmt)620 free_commit(PLpgSQL_stmt_commit *stmt)
621 {
622 }
623 
624 static void
free_rollback(PLpgSQL_stmt_rollback * stmt)625 free_rollback(PLpgSQL_stmt_rollback *stmt)
626 {
627 }
628 
629 static void
free_set(PLpgSQL_stmt_set * stmt)630 free_set(PLpgSQL_stmt_set *stmt)
631 {
632 	free_expr(stmt->expr);
633 }
634 
635 static void
free_exit(PLpgSQL_stmt_exit * stmt)636 free_exit(PLpgSQL_stmt_exit *stmt)
637 {
638 	free_expr(stmt->cond);
639 }
640 
641 static void
free_return(PLpgSQL_stmt_return * stmt)642 free_return(PLpgSQL_stmt_return *stmt)
643 {
644 	free_expr(stmt->expr);
645 }
646 
647 static void
free_return_next(PLpgSQL_stmt_return_next * stmt)648 free_return_next(PLpgSQL_stmt_return_next *stmt)
649 {
650 	free_expr(stmt->expr);
651 }
652 
653 static void
free_return_query(PLpgSQL_stmt_return_query * stmt)654 free_return_query(PLpgSQL_stmt_return_query *stmt)
655 {
656 	ListCell   *lc;
657 
658 	free_expr(stmt->query);
659 	free_expr(stmt->dynquery);
660 	foreach(lc, stmt->params)
661 	{
662 		free_expr((PLpgSQL_expr *) lfirst(lc));
663 	}
664 }
665 
666 static void
free_raise(PLpgSQL_stmt_raise * stmt)667 free_raise(PLpgSQL_stmt_raise *stmt)
668 {
669 	ListCell   *lc;
670 
671 	foreach(lc, stmt->params)
672 	{
673 		free_expr((PLpgSQL_expr *) lfirst(lc));
674 	}
675 	foreach(lc, stmt->options)
676 	{
677 		PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
678 
679 		free_expr(opt->expr);
680 	}
681 }
682 
683 static void
free_assert(PLpgSQL_stmt_assert * stmt)684 free_assert(PLpgSQL_stmt_assert *stmt)
685 {
686 	free_expr(stmt->cond);
687 	free_expr(stmt->message);
688 }
689 
690 static void
free_execsql(PLpgSQL_stmt_execsql * stmt)691 free_execsql(PLpgSQL_stmt_execsql *stmt)
692 {
693 	free_expr(stmt->sqlstmt);
694 }
695 
696 static void
free_dynexecute(PLpgSQL_stmt_dynexecute * stmt)697 free_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
698 {
699 	ListCell   *lc;
700 
701 	free_expr(stmt->query);
702 	foreach(lc, stmt->params)
703 	{
704 		free_expr((PLpgSQL_expr *) lfirst(lc));
705 	}
706 }
707 
708 static void
free_dynfors(PLpgSQL_stmt_dynfors * stmt)709 free_dynfors(PLpgSQL_stmt_dynfors *stmt)
710 {
711 	ListCell   *lc;
712 
713 	free_stmts(stmt->body);
714 	free_expr(stmt->query);
715 	foreach(lc, stmt->params)
716 	{
717 		free_expr((PLpgSQL_expr *) lfirst(lc));
718 	}
719 }
720 
721 static void
free_getdiag(PLpgSQL_stmt_getdiag * stmt)722 free_getdiag(PLpgSQL_stmt_getdiag *stmt)
723 {
724 }
725 
726 static void
free_expr(PLpgSQL_expr * expr)727 free_expr(PLpgSQL_expr *expr)
728 {
729 	if (expr && expr->plan)
730 	{
731 		SPI_freeplan(expr->plan);
732 		expr->plan = NULL;
733 	}
734 }
735 
736 void
plpgsql_free_function_memory(PLpgSQL_function * func)737 plpgsql_free_function_memory(PLpgSQL_function *func)
738 {
739 	int			i;
740 
741 	/* Better not call this on an in-use function */
742 	Assert(func->use_count == 0);
743 
744 	/* Release plans associated with variable declarations */
745 	for (i = 0; i < func->ndatums; i++)
746 	{
747 		PLpgSQL_datum *d = func->datums[i];
748 
749 		switch (d->dtype)
750 		{
751 			case PLPGSQL_DTYPE_VAR:
752 			case PLPGSQL_DTYPE_PROMISE:
753 				{
754 					PLpgSQL_var *var = (PLpgSQL_var *) d;
755 
756 					free_expr(var->default_val);
757 					free_expr(var->cursor_explicit_expr);
758 				}
759 				break;
760 			case PLPGSQL_DTYPE_ROW:
761 				break;
762 			case PLPGSQL_DTYPE_REC:
763 				{
764 					PLpgSQL_rec *rec = (PLpgSQL_rec *) d;
765 
766 					free_expr(rec->default_val);
767 				}
768 				break;
769 			case PLPGSQL_DTYPE_RECFIELD:
770 				break;
771 			case PLPGSQL_DTYPE_ARRAYELEM:
772 				free_expr(((PLpgSQL_arrayelem *) d)->subscript);
773 				break;
774 			default:
775 				elog(ERROR, "unrecognized data type: %d", d->dtype);
776 		}
777 	}
778 	func->ndatums = 0;
779 
780 	/* Release plans in statement tree */
781 	if (func->action)
782 		free_block(func->action);
783 	func->action = NULL;
784 
785 	/*
786 	 * And finally, release all memory except the PLpgSQL_function struct
787 	 * itself (which has to be kept around because there may be multiple
788 	 * fn_extra pointers to it).
789 	 */
790 	if (func->fn_cxt)
791 		MemoryContextDelete(func->fn_cxt);
792 	func->fn_cxt = NULL;
793 }
794 
795 
796 /**********************************************************************
797  * Debug functions for analyzing the compiled code
798  **********************************************************************/
799 static int	dump_indent;
800 
801 static void dump_ind(void);
802 static void dump_stmt(PLpgSQL_stmt *stmt);
803 static void dump_block(PLpgSQL_stmt_block *block);
804 static void dump_assign(PLpgSQL_stmt_assign *stmt);
805 static void dump_if(PLpgSQL_stmt_if *stmt);
806 static void dump_case(PLpgSQL_stmt_case *stmt);
807 static void dump_loop(PLpgSQL_stmt_loop *stmt);
808 static void dump_while(PLpgSQL_stmt_while *stmt);
809 static void dump_fori(PLpgSQL_stmt_fori *stmt);
810 static void dump_fors(PLpgSQL_stmt_fors *stmt);
811 static void dump_forc(PLpgSQL_stmt_forc *stmt);
812 static void dump_foreach_a(PLpgSQL_stmt_foreach_a *stmt);
813 static void dump_exit(PLpgSQL_stmt_exit *stmt);
814 static void dump_return(PLpgSQL_stmt_return *stmt);
815 static void dump_return_next(PLpgSQL_stmt_return_next *stmt);
816 static void dump_return_query(PLpgSQL_stmt_return_query *stmt);
817 static void dump_raise(PLpgSQL_stmt_raise *stmt);
818 static void dump_assert(PLpgSQL_stmt_assert *stmt);
819 static void dump_execsql(PLpgSQL_stmt_execsql *stmt);
820 static void dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
821 static void dump_dynfors(PLpgSQL_stmt_dynfors *stmt);
822 static void dump_getdiag(PLpgSQL_stmt_getdiag *stmt);
823 static void dump_open(PLpgSQL_stmt_open *stmt);
824 static void dump_fetch(PLpgSQL_stmt_fetch *stmt);
825 static void dump_cursor_direction(PLpgSQL_stmt_fetch *stmt);
826 static void dump_close(PLpgSQL_stmt_close *stmt);
827 static void dump_perform(PLpgSQL_stmt_perform *stmt);
828 static void dump_call(PLpgSQL_stmt_call *stmt);
829 static void dump_commit(PLpgSQL_stmt_commit *stmt);
830 static void dump_rollback(PLpgSQL_stmt_rollback *stmt);
831 static void dump_set(PLpgSQL_stmt_set *stmt);
832 static void dump_expr(PLpgSQL_expr *expr);
833 
834 
835 static void
dump_ind(void)836 dump_ind(void)
837 {
838 	int			i;
839 
840 	for (i = 0; i < dump_indent; i++)
841 		printf(" ");
842 }
843 
844 static void
dump_stmt(PLpgSQL_stmt * stmt)845 dump_stmt(PLpgSQL_stmt *stmt)
846 {
847 	printf("%3d:", stmt->lineno);
848 	switch (stmt->cmd_type)
849 	{
850 		case PLPGSQL_STMT_BLOCK:
851 			dump_block((PLpgSQL_stmt_block *) stmt);
852 			break;
853 		case PLPGSQL_STMT_ASSIGN:
854 			dump_assign((PLpgSQL_stmt_assign *) stmt);
855 			break;
856 		case PLPGSQL_STMT_IF:
857 			dump_if((PLpgSQL_stmt_if *) stmt);
858 			break;
859 		case PLPGSQL_STMT_CASE:
860 			dump_case((PLpgSQL_stmt_case *) stmt);
861 			break;
862 		case PLPGSQL_STMT_LOOP:
863 			dump_loop((PLpgSQL_stmt_loop *) stmt);
864 			break;
865 		case PLPGSQL_STMT_WHILE:
866 			dump_while((PLpgSQL_stmt_while *) stmt);
867 			break;
868 		case PLPGSQL_STMT_FORI:
869 			dump_fori((PLpgSQL_stmt_fori *) stmt);
870 			break;
871 		case PLPGSQL_STMT_FORS:
872 			dump_fors((PLpgSQL_stmt_fors *) stmt);
873 			break;
874 		case PLPGSQL_STMT_FORC:
875 			dump_forc((PLpgSQL_stmt_forc *) stmt);
876 			break;
877 		case PLPGSQL_STMT_FOREACH_A:
878 			dump_foreach_a((PLpgSQL_stmt_foreach_a *) stmt);
879 			break;
880 		case PLPGSQL_STMT_EXIT:
881 			dump_exit((PLpgSQL_stmt_exit *) stmt);
882 			break;
883 		case PLPGSQL_STMT_RETURN:
884 			dump_return((PLpgSQL_stmt_return *) stmt);
885 			break;
886 		case PLPGSQL_STMT_RETURN_NEXT:
887 			dump_return_next((PLpgSQL_stmt_return_next *) stmt);
888 			break;
889 		case PLPGSQL_STMT_RETURN_QUERY:
890 			dump_return_query((PLpgSQL_stmt_return_query *) stmt);
891 			break;
892 		case PLPGSQL_STMT_RAISE:
893 			dump_raise((PLpgSQL_stmt_raise *) stmt);
894 			break;
895 		case PLPGSQL_STMT_ASSERT:
896 			dump_assert((PLpgSQL_stmt_assert *) stmt);
897 			break;
898 		case PLPGSQL_STMT_EXECSQL:
899 			dump_execsql((PLpgSQL_stmt_execsql *) stmt);
900 			break;
901 		case PLPGSQL_STMT_DYNEXECUTE:
902 			dump_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
903 			break;
904 		case PLPGSQL_STMT_DYNFORS:
905 			dump_dynfors((PLpgSQL_stmt_dynfors *) stmt);
906 			break;
907 		case PLPGSQL_STMT_GETDIAG:
908 			dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
909 			break;
910 		case PLPGSQL_STMT_OPEN:
911 			dump_open((PLpgSQL_stmt_open *) stmt);
912 			break;
913 		case PLPGSQL_STMT_FETCH:
914 			dump_fetch((PLpgSQL_stmt_fetch *) stmt);
915 			break;
916 		case PLPGSQL_STMT_CLOSE:
917 			dump_close((PLpgSQL_stmt_close *) stmt);
918 			break;
919 		case PLPGSQL_STMT_PERFORM:
920 			dump_perform((PLpgSQL_stmt_perform *) stmt);
921 			break;
922 		case PLPGSQL_STMT_CALL:
923 			dump_call((PLpgSQL_stmt_call *) stmt);
924 			break;
925 		case PLPGSQL_STMT_COMMIT:
926 			dump_commit((PLpgSQL_stmt_commit *) stmt);
927 			break;
928 		case PLPGSQL_STMT_ROLLBACK:
929 			dump_rollback((PLpgSQL_stmt_rollback *) stmt);
930 			break;
931 		case PLPGSQL_STMT_SET:
932 			dump_set((PLpgSQL_stmt_set *) stmt);
933 			break;
934 		default:
935 			elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
936 			break;
937 	}
938 }
939 
940 static void
dump_stmts(List * stmts)941 dump_stmts(List *stmts)
942 {
943 	ListCell   *s;
944 
945 	dump_indent += 2;
946 	foreach(s, stmts)
947 		dump_stmt((PLpgSQL_stmt *) lfirst(s));
948 	dump_indent -= 2;
949 }
950 
951 static void
dump_block(PLpgSQL_stmt_block * block)952 dump_block(PLpgSQL_stmt_block *block)
953 {
954 	char	   *name;
955 
956 	if (block->label == NULL)
957 		name = "*unnamed*";
958 	else
959 		name = block->label;
960 
961 	dump_ind();
962 	printf("BLOCK <<%s>>\n", name);
963 
964 	dump_stmts(block->body);
965 
966 	if (block->exceptions)
967 	{
968 		ListCell   *e;
969 
970 		foreach(e, block->exceptions->exc_list)
971 		{
972 			PLpgSQL_exception *exc = (PLpgSQL_exception *) lfirst(e);
973 			PLpgSQL_condition *cond;
974 
975 			dump_ind();
976 			printf("    EXCEPTION WHEN ");
977 			for (cond = exc->conditions; cond; cond = cond->next)
978 			{
979 				if (cond != exc->conditions)
980 					printf(" OR ");
981 				printf("%s", cond->condname);
982 			}
983 			printf(" THEN\n");
984 			dump_stmts(exc->action);
985 		}
986 	}
987 
988 	dump_ind();
989 	printf("    END -- %s\n", name);
990 }
991 
992 static void
dump_assign(PLpgSQL_stmt_assign * stmt)993 dump_assign(PLpgSQL_stmt_assign *stmt)
994 {
995 	dump_ind();
996 	printf("ASSIGN var %d := ", stmt->varno);
997 	dump_expr(stmt->expr);
998 	printf("\n");
999 }
1000 
1001 static void
dump_if(PLpgSQL_stmt_if * stmt)1002 dump_if(PLpgSQL_stmt_if *stmt)
1003 {
1004 	ListCell   *l;
1005 
1006 	dump_ind();
1007 	printf("IF ");
1008 	dump_expr(stmt->cond);
1009 	printf(" THEN\n");
1010 	dump_stmts(stmt->then_body);
1011 	foreach(l, stmt->elsif_list)
1012 	{
1013 		PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(l);
1014 
1015 		dump_ind();
1016 		printf("    ELSIF ");
1017 		dump_expr(elif->cond);
1018 		printf(" THEN\n");
1019 		dump_stmts(elif->stmts);
1020 	}
1021 	if (stmt->else_body != NIL)
1022 	{
1023 		dump_ind();
1024 		printf("    ELSE\n");
1025 		dump_stmts(stmt->else_body);
1026 	}
1027 	dump_ind();
1028 	printf("    ENDIF\n");
1029 }
1030 
1031 static void
dump_case(PLpgSQL_stmt_case * stmt)1032 dump_case(PLpgSQL_stmt_case *stmt)
1033 {
1034 	ListCell   *l;
1035 
1036 	dump_ind();
1037 	printf("CASE %d ", stmt->t_varno);
1038 	if (stmt->t_expr)
1039 		dump_expr(stmt->t_expr);
1040 	printf("\n");
1041 	dump_indent += 6;
1042 	foreach(l, stmt->case_when_list)
1043 	{
1044 		PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
1045 
1046 		dump_ind();
1047 		printf("WHEN ");
1048 		dump_expr(cwt->expr);
1049 		printf("\n");
1050 		dump_ind();
1051 		printf("THEN\n");
1052 		dump_indent += 2;
1053 		dump_stmts(cwt->stmts);
1054 		dump_indent -= 2;
1055 	}
1056 	if (stmt->have_else)
1057 	{
1058 		dump_ind();
1059 		printf("ELSE\n");
1060 		dump_indent += 2;
1061 		dump_stmts(stmt->else_stmts);
1062 		dump_indent -= 2;
1063 	}
1064 	dump_indent -= 6;
1065 	dump_ind();
1066 	printf("    ENDCASE\n");
1067 }
1068 
1069 static void
dump_loop(PLpgSQL_stmt_loop * stmt)1070 dump_loop(PLpgSQL_stmt_loop *stmt)
1071 {
1072 	dump_ind();
1073 	printf("LOOP\n");
1074 
1075 	dump_stmts(stmt->body);
1076 
1077 	dump_ind();
1078 	printf("    ENDLOOP\n");
1079 }
1080 
1081 static void
dump_while(PLpgSQL_stmt_while * stmt)1082 dump_while(PLpgSQL_stmt_while *stmt)
1083 {
1084 	dump_ind();
1085 	printf("WHILE ");
1086 	dump_expr(stmt->cond);
1087 	printf("\n");
1088 
1089 	dump_stmts(stmt->body);
1090 
1091 	dump_ind();
1092 	printf("    ENDWHILE\n");
1093 }
1094 
1095 static void
dump_fori(PLpgSQL_stmt_fori * stmt)1096 dump_fori(PLpgSQL_stmt_fori *stmt)
1097 {
1098 	dump_ind();
1099 	printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
1100 
1101 	dump_indent += 2;
1102 	dump_ind();
1103 	printf("    lower = ");
1104 	dump_expr(stmt->lower);
1105 	printf("\n");
1106 	dump_ind();
1107 	printf("    upper = ");
1108 	dump_expr(stmt->upper);
1109 	printf("\n");
1110 	if (stmt->step)
1111 	{
1112 		dump_ind();
1113 		printf("    step = ");
1114 		dump_expr(stmt->step);
1115 		printf("\n");
1116 	}
1117 	dump_indent -= 2;
1118 
1119 	dump_stmts(stmt->body);
1120 
1121 	dump_ind();
1122 	printf("    ENDFORI\n");
1123 }
1124 
1125 static void
dump_fors(PLpgSQL_stmt_fors * stmt)1126 dump_fors(PLpgSQL_stmt_fors *stmt)
1127 {
1128 	dump_ind();
1129 	printf("FORS %s ", stmt->var->refname);
1130 	dump_expr(stmt->query);
1131 	printf("\n");
1132 
1133 	dump_stmts(stmt->body);
1134 
1135 	dump_ind();
1136 	printf("    ENDFORS\n");
1137 }
1138 
1139 static void
dump_forc(PLpgSQL_stmt_forc * stmt)1140 dump_forc(PLpgSQL_stmt_forc *stmt)
1141 {
1142 	dump_ind();
1143 	printf("FORC %s ", stmt->var->refname);
1144 	printf("curvar=%d\n", stmt->curvar);
1145 
1146 	dump_indent += 2;
1147 	if (stmt->argquery != NULL)
1148 	{
1149 		dump_ind();
1150 		printf("  arguments = ");
1151 		dump_expr(stmt->argquery);
1152 		printf("\n");
1153 	}
1154 	dump_indent -= 2;
1155 
1156 	dump_stmts(stmt->body);
1157 
1158 	dump_ind();
1159 	printf("    ENDFORC\n");
1160 }
1161 
1162 static void
dump_foreach_a(PLpgSQL_stmt_foreach_a * stmt)1163 dump_foreach_a(PLpgSQL_stmt_foreach_a *stmt)
1164 {
1165 	dump_ind();
1166 	printf("FOREACHA var %d ", stmt->varno);
1167 	if (stmt->slice != 0)
1168 		printf("SLICE %d ", stmt->slice);
1169 	printf("IN ");
1170 	dump_expr(stmt->expr);
1171 	printf("\n");
1172 
1173 	dump_stmts(stmt->body);
1174 
1175 	dump_ind();
1176 	printf("    ENDFOREACHA");
1177 }
1178 
1179 static void
dump_open(PLpgSQL_stmt_open * stmt)1180 dump_open(PLpgSQL_stmt_open *stmt)
1181 {
1182 	dump_ind();
1183 	printf("OPEN curvar=%d\n", stmt->curvar);
1184 
1185 	dump_indent += 2;
1186 	if (stmt->argquery != NULL)
1187 	{
1188 		dump_ind();
1189 		printf("  arguments = '");
1190 		dump_expr(stmt->argquery);
1191 		printf("'\n");
1192 	}
1193 	if (stmt->query != NULL)
1194 	{
1195 		dump_ind();
1196 		printf("  query = '");
1197 		dump_expr(stmt->query);
1198 		printf("'\n");
1199 	}
1200 	if (stmt->dynquery != NULL)
1201 	{
1202 		dump_ind();
1203 		printf("  execute = '");
1204 		dump_expr(stmt->dynquery);
1205 		printf("'\n");
1206 
1207 		if (stmt->params != NIL)
1208 		{
1209 			ListCell   *lc;
1210 			int			i;
1211 
1212 			dump_indent += 2;
1213 			dump_ind();
1214 			printf("    USING\n");
1215 			dump_indent += 2;
1216 			i = 1;
1217 			foreach(lc, stmt->params)
1218 			{
1219 				dump_ind();
1220 				printf("    parameter $%d: ", i++);
1221 				dump_expr((PLpgSQL_expr *) lfirst(lc));
1222 				printf("\n");
1223 			}
1224 			dump_indent -= 4;
1225 		}
1226 	}
1227 	dump_indent -= 2;
1228 }
1229 
1230 static void
dump_fetch(PLpgSQL_stmt_fetch * stmt)1231 dump_fetch(PLpgSQL_stmt_fetch *stmt)
1232 {
1233 	dump_ind();
1234 
1235 	if (!stmt->is_move)
1236 	{
1237 		printf("FETCH curvar=%d\n", stmt->curvar);
1238 		dump_cursor_direction(stmt);
1239 
1240 		dump_indent += 2;
1241 		if (stmt->target != NULL)
1242 		{
1243 			dump_ind();
1244 			printf("    target = %d %s\n",
1245 				   stmt->target->dno, stmt->target->refname);
1246 		}
1247 		dump_indent -= 2;
1248 	}
1249 	else
1250 	{
1251 		printf("MOVE curvar=%d\n", stmt->curvar);
1252 		dump_cursor_direction(stmt);
1253 	}
1254 }
1255 
1256 static void
dump_cursor_direction(PLpgSQL_stmt_fetch * stmt)1257 dump_cursor_direction(PLpgSQL_stmt_fetch *stmt)
1258 {
1259 	dump_indent += 2;
1260 	dump_ind();
1261 	switch (stmt->direction)
1262 	{
1263 		case FETCH_FORWARD:
1264 			printf("    FORWARD ");
1265 			break;
1266 		case FETCH_BACKWARD:
1267 			printf("    BACKWARD ");
1268 			break;
1269 		case FETCH_ABSOLUTE:
1270 			printf("    ABSOLUTE ");
1271 			break;
1272 		case FETCH_RELATIVE:
1273 			printf("    RELATIVE ");
1274 			break;
1275 		default:
1276 			printf("??? unknown cursor direction %d", stmt->direction);
1277 	}
1278 
1279 	if (stmt->expr)
1280 	{
1281 		dump_expr(stmt->expr);
1282 		printf("\n");
1283 	}
1284 	else
1285 		printf("%ld\n", stmt->how_many);
1286 
1287 	dump_indent -= 2;
1288 }
1289 
1290 static void
dump_close(PLpgSQL_stmt_close * stmt)1291 dump_close(PLpgSQL_stmt_close *stmt)
1292 {
1293 	dump_ind();
1294 	printf("CLOSE curvar=%d\n", stmt->curvar);
1295 }
1296 
1297 static void
dump_perform(PLpgSQL_stmt_perform * stmt)1298 dump_perform(PLpgSQL_stmt_perform *stmt)
1299 {
1300 	dump_ind();
1301 	printf("PERFORM expr = ");
1302 	dump_expr(stmt->expr);
1303 	printf("\n");
1304 }
1305 
1306 static void
dump_call(PLpgSQL_stmt_call * stmt)1307 dump_call(PLpgSQL_stmt_call *stmt)
1308 {
1309 	dump_ind();
1310 	printf("%s expr = ", stmt->is_call ? "CALL" : "DO");
1311 	dump_expr(stmt->expr);
1312 	printf("\n");
1313 }
1314 
1315 static void
dump_commit(PLpgSQL_stmt_commit * stmt)1316 dump_commit(PLpgSQL_stmt_commit *stmt)
1317 {
1318 	dump_ind();
1319 	if (stmt->chain)
1320 		printf("COMMIT AND CHAIN\n");
1321 	else
1322 		printf("COMMIT\n");
1323 }
1324 
1325 static void
dump_rollback(PLpgSQL_stmt_rollback * stmt)1326 dump_rollback(PLpgSQL_stmt_rollback *stmt)
1327 {
1328 	dump_ind();
1329 	if (stmt->chain)
1330 		printf("ROLLBACK AND CHAIN\n");
1331 	else
1332 		printf("ROLLBACK\n");
1333 }
1334 
1335 static void
dump_set(PLpgSQL_stmt_set * stmt)1336 dump_set(PLpgSQL_stmt_set *stmt)
1337 {
1338 	dump_ind();
1339 	printf("%s\n", stmt->expr->query);
1340 }
1341 
1342 static void
dump_exit(PLpgSQL_stmt_exit * stmt)1343 dump_exit(PLpgSQL_stmt_exit *stmt)
1344 {
1345 	dump_ind();
1346 	printf("%s", stmt->is_exit ? "EXIT" : "CONTINUE");
1347 	if (stmt->label != NULL)
1348 		printf(" label='%s'", stmt->label);
1349 	if (stmt->cond != NULL)
1350 	{
1351 		printf(" WHEN ");
1352 		dump_expr(stmt->cond);
1353 	}
1354 	printf("\n");
1355 }
1356 
1357 static void
dump_return(PLpgSQL_stmt_return * stmt)1358 dump_return(PLpgSQL_stmt_return *stmt)
1359 {
1360 	dump_ind();
1361 	printf("RETURN ");
1362 	if (stmt->retvarno >= 0)
1363 		printf("variable %d", stmt->retvarno);
1364 	else if (stmt->expr != NULL)
1365 		dump_expr(stmt->expr);
1366 	else
1367 		printf("NULL");
1368 	printf("\n");
1369 }
1370 
1371 static void
dump_return_next(PLpgSQL_stmt_return_next * stmt)1372 dump_return_next(PLpgSQL_stmt_return_next *stmt)
1373 {
1374 	dump_ind();
1375 	printf("RETURN NEXT ");
1376 	if (stmt->retvarno >= 0)
1377 		printf("variable %d", stmt->retvarno);
1378 	else if (stmt->expr != NULL)
1379 		dump_expr(stmt->expr);
1380 	else
1381 		printf("NULL");
1382 	printf("\n");
1383 }
1384 
1385 static void
dump_return_query(PLpgSQL_stmt_return_query * stmt)1386 dump_return_query(PLpgSQL_stmt_return_query *stmt)
1387 {
1388 	dump_ind();
1389 	if (stmt->query)
1390 	{
1391 		printf("RETURN QUERY ");
1392 		dump_expr(stmt->query);
1393 		printf("\n");
1394 	}
1395 	else
1396 	{
1397 		printf("RETURN QUERY EXECUTE ");
1398 		dump_expr(stmt->dynquery);
1399 		printf("\n");
1400 		if (stmt->params != NIL)
1401 		{
1402 			ListCell   *lc;
1403 			int			i;
1404 
1405 			dump_indent += 2;
1406 			dump_ind();
1407 			printf("    USING\n");
1408 			dump_indent += 2;
1409 			i = 1;
1410 			foreach(lc, stmt->params)
1411 			{
1412 				dump_ind();
1413 				printf("    parameter $%d: ", i++);
1414 				dump_expr((PLpgSQL_expr *) lfirst(lc));
1415 				printf("\n");
1416 			}
1417 			dump_indent -= 4;
1418 		}
1419 	}
1420 }
1421 
1422 static void
dump_raise(PLpgSQL_stmt_raise * stmt)1423 dump_raise(PLpgSQL_stmt_raise *stmt)
1424 {
1425 	ListCell   *lc;
1426 	int			i = 0;
1427 
1428 	dump_ind();
1429 	printf("RAISE level=%d", stmt->elog_level);
1430 	if (stmt->condname)
1431 		printf(" condname='%s'", stmt->condname);
1432 	if (stmt->message)
1433 		printf(" message='%s'", stmt->message);
1434 	printf("\n");
1435 	dump_indent += 2;
1436 	foreach(lc, stmt->params)
1437 	{
1438 		dump_ind();
1439 		printf("    parameter %d: ", i++);
1440 		dump_expr((PLpgSQL_expr *) lfirst(lc));
1441 		printf("\n");
1442 	}
1443 	if (stmt->options)
1444 	{
1445 		dump_ind();
1446 		printf("    USING\n");
1447 		dump_indent += 2;
1448 		foreach(lc, stmt->options)
1449 		{
1450 			PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
1451 
1452 			dump_ind();
1453 			switch (opt->opt_type)
1454 			{
1455 				case PLPGSQL_RAISEOPTION_ERRCODE:
1456 					printf("    ERRCODE = ");
1457 					break;
1458 				case PLPGSQL_RAISEOPTION_MESSAGE:
1459 					printf("    MESSAGE = ");
1460 					break;
1461 				case PLPGSQL_RAISEOPTION_DETAIL:
1462 					printf("    DETAIL = ");
1463 					break;
1464 				case PLPGSQL_RAISEOPTION_HINT:
1465 					printf("    HINT = ");
1466 					break;
1467 				case PLPGSQL_RAISEOPTION_COLUMN:
1468 					printf("    COLUMN = ");
1469 					break;
1470 				case PLPGSQL_RAISEOPTION_CONSTRAINT:
1471 					printf("    CONSTRAINT = ");
1472 					break;
1473 				case PLPGSQL_RAISEOPTION_DATATYPE:
1474 					printf("    DATATYPE = ");
1475 					break;
1476 				case PLPGSQL_RAISEOPTION_TABLE:
1477 					printf("    TABLE = ");
1478 					break;
1479 				case PLPGSQL_RAISEOPTION_SCHEMA:
1480 					printf("    SCHEMA = ");
1481 					break;
1482 			}
1483 			dump_expr(opt->expr);
1484 			printf("\n");
1485 		}
1486 		dump_indent -= 2;
1487 	}
1488 	dump_indent -= 2;
1489 }
1490 
1491 static void
dump_assert(PLpgSQL_stmt_assert * stmt)1492 dump_assert(PLpgSQL_stmt_assert *stmt)
1493 {
1494 	dump_ind();
1495 	printf("ASSERT ");
1496 	dump_expr(stmt->cond);
1497 	printf("\n");
1498 
1499 	dump_indent += 2;
1500 	if (stmt->message != NULL)
1501 	{
1502 		dump_ind();
1503 		printf("    MESSAGE = ");
1504 		dump_expr(stmt->message);
1505 		printf("\n");
1506 	}
1507 	dump_indent -= 2;
1508 }
1509 
1510 static void
dump_execsql(PLpgSQL_stmt_execsql * stmt)1511 dump_execsql(PLpgSQL_stmt_execsql *stmt)
1512 {
1513 	dump_ind();
1514 	printf("EXECSQL ");
1515 	dump_expr(stmt->sqlstmt);
1516 	printf("\n");
1517 
1518 	dump_indent += 2;
1519 	if (stmt->target != NULL)
1520 	{
1521 		dump_ind();
1522 		printf("    INTO%s target = %d %s\n",
1523 			   stmt->strict ? " STRICT" : "",
1524 			   stmt->target->dno, stmt->target->refname);
1525 	}
1526 	dump_indent -= 2;
1527 }
1528 
1529 static void
dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt)1530 dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
1531 {
1532 	dump_ind();
1533 	printf("EXECUTE ");
1534 	dump_expr(stmt->query);
1535 	printf("\n");
1536 
1537 	dump_indent += 2;
1538 	if (stmt->target != NULL)
1539 	{
1540 		dump_ind();
1541 		printf("    INTO%s target = %d %s\n",
1542 			   stmt->strict ? " STRICT" : "",
1543 			   stmt->target->dno, stmt->target->refname);
1544 	}
1545 	if (stmt->params != NIL)
1546 	{
1547 		ListCell   *lc;
1548 		int			i;
1549 
1550 		dump_ind();
1551 		printf("    USING\n");
1552 		dump_indent += 2;
1553 		i = 1;
1554 		foreach(lc, stmt->params)
1555 		{
1556 			dump_ind();
1557 			printf("    parameter %d: ", i++);
1558 			dump_expr((PLpgSQL_expr *) lfirst(lc));
1559 			printf("\n");
1560 		}
1561 		dump_indent -= 2;
1562 	}
1563 	dump_indent -= 2;
1564 }
1565 
1566 static void
dump_dynfors(PLpgSQL_stmt_dynfors * stmt)1567 dump_dynfors(PLpgSQL_stmt_dynfors *stmt)
1568 {
1569 	dump_ind();
1570 	printf("FORS %s EXECUTE ", stmt->var->refname);
1571 	dump_expr(stmt->query);
1572 	printf("\n");
1573 	if (stmt->params != NIL)
1574 	{
1575 		ListCell   *lc;
1576 		int			i;
1577 
1578 		dump_indent += 2;
1579 		dump_ind();
1580 		printf("    USING\n");
1581 		dump_indent += 2;
1582 		i = 1;
1583 		foreach(lc, stmt->params)
1584 		{
1585 			dump_ind();
1586 			printf("    parameter $%d: ", i++);
1587 			dump_expr((PLpgSQL_expr *) lfirst(lc));
1588 			printf("\n");
1589 		}
1590 		dump_indent -= 4;
1591 	}
1592 	dump_stmts(stmt->body);
1593 	dump_ind();
1594 	printf("    ENDFORS\n");
1595 }
1596 
1597 static void
dump_getdiag(PLpgSQL_stmt_getdiag * stmt)1598 dump_getdiag(PLpgSQL_stmt_getdiag *stmt)
1599 {
1600 	ListCell   *lc;
1601 
1602 	dump_ind();
1603 	printf("GET %s DIAGNOSTICS ", stmt->is_stacked ? "STACKED" : "CURRENT");
1604 	foreach(lc, stmt->diag_items)
1605 	{
1606 		PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
1607 
1608 		if (lc != list_head(stmt->diag_items))
1609 			printf(", ");
1610 
1611 		printf("{var %d} = %s", diag_item->target,
1612 			   plpgsql_getdiag_kindname(diag_item->kind));
1613 	}
1614 	printf("\n");
1615 }
1616 
1617 static void
dump_expr(PLpgSQL_expr * expr)1618 dump_expr(PLpgSQL_expr *expr)
1619 {
1620 	printf("'%s'", expr->query);
1621 }
1622 
1623 void
plpgsql_dumptree(PLpgSQL_function * func)1624 plpgsql_dumptree(PLpgSQL_function *func)
1625 {
1626 	int			i;
1627 	PLpgSQL_datum *d;
1628 
1629 	printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
1630 		   func->fn_signature);
1631 
1632 	printf("\nFunction's data area:\n");
1633 	for (i = 0; i < func->ndatums; i++)
1634 	{
1635 		d = func->datums[i];
1636 
1637 		printf("    entry %d: ", i);
1638 		switch (d->dtype)
1639 		{
1640 			case PLPGSQL_DTYPE_VAR:
1641 			case PLPGSQL_DTYPE_PROMISE:
1642 				{
1643 					PLpgSQL_var *var = (PLpgSQL_var *) d;
1644 
1645 					printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
1646 						   var->refname, var->datatype->typname,
1647 						   var->datatype->typoid,
1648 						   var->datatype->atttypmod);
1649 					if (var->isconst)
1650 						printf("                                  CONSTANT\n");
1651 					if (var->notnull)
1652 						printf("                                  NOT NULL\n");
1653 					if (var->default_val != NULL)
1654 					{
1655 						printf("                                  DEFAULT ");
1656 						dump_expr(var->default_val);
1657 						printf("\n");
1658 					}
1659 					if (var->cursor_explicit_expr != NULL)
1660 					{
1661 						if (var->cursor_explicit_argrow >= 0)
1662 							printf("                                  CURSOR argument row %d\n", var->cursor_explicit_argrow);
1663 
1664 						printf("                                  CURSOR IS ");
1665 						dump_expr(var->cursor_explicit_expr);
1666 						printf("\n");
1667 					}
1668 					if (var->promise != PLPGSQL_PROMISE_NONE)
1669 						printf("                                  PROMISE %d\n",
1670 							   (int) var->promise);
1671 				}
1672 				break;
1673 			case PLPGSQL_DTYPE_ROW:
1674 				{
1675 					PLpgSQL_row *row = (PLpgSQL_row *) d;
1676 					int			i;
1677 
1678 					printf("ROW %-16s fields", row->refname);
1679 					for (i = 0; i < row->nfields; i++)
1680 					{
1681 						printf(" %s=var %d", row->fieldnames[i],
1682 							   row->varnos[i]);
1683 					}
1684 					printf("\n");
1685 				}
1686 				break;
1687 			case PLPGSQL_DTYPE_REC:
1688 				printf("REC %-16s typoid %u\n",
1689 					   ((PLpgSQL_rec *) d)->refname,
1690 					   ((PLpgSQL_rec *) d)->rectypeid);
1691 				if (((PLpgSQL_rec *) d)->isconst)
1692 					printf("                                  CONSTANT\n");
1693 				if (((PLpgSQL_rec *) d)->notnull)
1694 					printf("                                  NOT NULL\n");
1695 				if (((PLpgSQL_rec *) d)->default_val != NULL)
1696 				{
1697 					printf("                                  DEFAULT ");
1698 					dump_expr(((PLpgSQL_rec *) d)->default_val);
1699 					printf("\n");
1700 				}
1701 				break;
1702 			case PLPGSQL_DTYPE_RECFIELD:
1703 				printf("RECFIELD %-16s of REC %d\n",
1704 					   ((PLpgSQL_recfield *) d)->fieldname,
1705 					   ((PLpgSQL_recfield *) d)->recparentno);
1706 				break;
1707 			case PLPGSQL_DTYPE_ARRAYELEM:
1708 				printf("ARRAYELEM of VAR %d subscript ",
1709 					   ((PLpgSQL_arrayelem *) d)->arrayparentno);
1710 				dump_expr(((PLpgSQL_arrayelem *) d)->subscript);
1711 				printf("\n");
1712 				break;
1713 			default:
1714 				printf("??? unknown data type %d\n", d->dtype);
1715 		}
1716 	}
1717 	printf("\nFunction's statements:\n");
1718 
1719 	dump_indent = 0;
1720 	printf("%3d:", func->action->lineno);
1721 	dump_block(func->action);
1722 	printf("\nEnd of execution tree of function %s\n\n", func->fn_signature);
1723 	fflush(stdout);
1724 }
1725