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