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