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