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