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