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