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