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