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