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