PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pl_funcs.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pl_funcs.c - Misc functions for the PL/pgSQL
4 * procedural language
5 *
6 * Portions Copyright (c) 1996-2025, 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 */
35static PLpgSQL_nsitem *ns_top = NULL;
36
37
38/* ----------
39 * plpgsql_ns_init Initialize namespace processing for a new function
40 * ----------
41 */
42void
44{
45 ns_top = NULL;
46}
47
48
49/* ----------
50 * plpgsql_ns_push Create a new namespace level
51 * ----------
52 */
53void
55{
56 if (label == NULL)
57 label = "";
59}
60
61
62/* ----------
63 * plpgsql_ns_pop Pop entries back to (and including) the last label
64 * ----------
65 */
66void
68{
69 Assert(ns_top != NULL);
73}
74
75
76/* ----------
77 * plpgsql_ns_top Fetch the current namespace chain end
78 * ----------
79 */
82{
83 return ns_top;
84}
85
86
87/* ----------
88 * plpgsql_ns_additem Add an item to the current namespace chain
89 * ----------
90 */
91void
92plpgsql_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 nse = palloc(offsetof(PLpgSQL_nsitem, name) + strlen(name) + 1);
101 nse->itemtype = itemtype;
102 nse->itemno = itemno;
103 nse->prev = ns_top;
104 strcpy(nse->name, name);
105 ns_top = nse;
106}
107
108
109/* ----------
110 * plpgsql_ns_lookup Lookup an identifier in the given namespace chain
111 *
112 * Note that this only searches for variables, not labels.
113 *
114 * If localmode is true, only the topmost block level is searched.
115 *
116 * name1 must be non-NULL. Pass NULL for name2 and/or name3 if parsing a name
117 * with fewer than three components.
118 *
119 * If names_used isn't NULL, *names_used receives the number of names
120 * matched: 0 if no match, 1 if name1 matched an unqualified variable name,
121 * 2 if name1 and name2 matched a block label + variable name.
122 *
123 * Note that name3 is never directly matched to anything. However, if it
124 * isn't NULL, we will disregard qualified matches to scalar variables.
125 * Similarly, if name2 isn't NULL, we disregard unqualified matches to
126 * scalar variables.
127 * ----------
128 */
130plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode,
131 const char *name1, const char *name2, const char *name3,
132 int *names_used)
133{
134 /* Outer loop iterates once per block level in the namespace chain */
135 while (ns_cur != NULL)
136 {
137 PLpgSQL_nsitem *nsitem;
138
139 /* Check this level for unqualified match to variable name */
140 for (nsitem = ns_cur;
142 nsitem = nsitem->prev)
143 {
144 if (strcmp(nsitem->name, name1) == 0)
145 {
146 if (name2 == NULL ||
147 nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
148 {
149 if (names_used)
150 *names_used = 1;
151 return nsitem;
152 }
153 }
154 }
155
156 /* Check this level for qualified match to variable name */
157 if (name2 != NULL &&
158 strcmp(nsitem->name, name1) == 0)
159 {
160 for (nsitem = ns_cur;
162 nsitem = nsitem->prev)
163 {
164 if (strcmp(nsitem->name, name2) == 0)
165 {
166 if (name3 == NULL ||
167 nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
168 {
169 if (names_used)
170 *names_used = 2;
171 return nsitem;
172 }
173 }
174 }
175 }
176
177 if (localmode)
178 break; /* do not look into upper levels */
179
180 ns_cur = nsitem->prev;
181 }
182
183 /* This is just to suppress possibly-uninitialized-variable warnings */
184 if (names_used)
185 *names_used = 0;
186 return NULL; /* No match found */
187}
188
189
190/* ----------
191 * plpgsql_ns_lookup_label Lookup a label in the given namespace chain
192 * ----------
193 */
196{
197 while (ns_cur != NULL)
198 {
199 if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL &&
200 strcmp(ns_cur->name, name) == 0)
201 return ns_cur;
202 ns_cur = ns_cur->prev;
203 }
204
205 return NULL; /* label not found */
206}
207
208
209/* ----------
210 * plpgsql_ns_find_nearest_loop Find innermost loop label in namespace chain
211 * ----------
212 */
215{
216 while (ns_cur != NULL)
217 {
218 if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL &&
219 ns_cur->itemno == PLPGSQL_LABEL_LOOP)
220 return ns_cur;
221 ns_cur = ns_cur->prev;
222 }
223
224 return NULL; /* no loop found */
225}
226
227
228/*
229 * Statement type as a string, for use in error messages etc.
230 */
231const char *
233{
234 switch (stmt->cmd_type)
235 {
237 return _("statement block");
239 return _("assignment");
240 case PLPGSQL_STMT_IF:
241 return "IF";
243 return "CASE";
245 return "LOOP";
247 return "WHILE";
249 return _("FOR with integer loop variable");
251 return _("FOR over SELECT rows");
253 return _("FOR over cursor");
255 return _("FOREACH over array");
257 return ((PLpgSQL_stmt_exit *) stmt)->is_exit ? "EXIT" : "CONTINUE";
259 return "RETURN";
261 return "RETURN NEXT";
263 return "RETURN QUERY";
265 return "RAISE";
267 return "ASSERT";
269 return _("SQL statement");
271 return "EXECUTE";
273 return _("FOR over EXECUTE statement");
275 return ((PLpgSQL_stmt_getdiag *) stmt)->is_stacked ?
276 "GET STACKED DIAGNOSTICS" : "GET DIAGNOSTICS";
278 return "OPEN";
280 return ((PLpgSQL_stmt_fetch *) stmt)->is_move ? "MOVE" : "FETCH";
282 return "CLOSE";
284 return "PERFORM";
286 return ((PLpgSQL_stmt_call *) stmt)->is_call ? "CALL" : "DO";
288 return "COMMIT";
290 return "ROLLBACK";
291 }
292
293 return "unknown";
294}
295
296/*
297 * GET DIAGNOSTICS item name as a string, for use in error messages etc.
298 */
299const char *
301{
302 switch (kind)
303 {
305 return "ROW_COUNT";
307 return "PG_ROUTINE_OID";
309 return "PG_CONTEXT";
311 return "PG_EXCEPTION_CONTEXT";
313 return "PG_EXCEPTION_DETAIL";
315 return "PG_EXCEPTION_HINT";
317 return "RETURNED_SQLSTATE";
319 return "COLUMN_NAME";
321 return "CONSTRAINT_NAME";
323 return "PG_DATATYPE_NAME";
325 return "MESSAGE_TEXT";
327 return "TABLE_NAME";
329 return "SCHEMA_NAME";
330 }
331
332 return "unknown";
333}
334
335
336/**********************************************************************
337 * Support for recursing through a PL/pgSQL statement tree
338 *
339 * The point of this code is to encapsulate knowledge of where the
340 * sub-statements and expressions are in a statement tree, avoiding
341 * duplication of code. The caller supplies two callbacks, one to
342 * be invoked on statements and one to be invoked on expressions.
343 * (The recursion should be started by invoking the statement callback
344 * on function->action.) The statement callback should do any
345 * statement-type-specific action it needs, then recurse by calling
346 * plpgsql_statement_tree_walker(). The expression callback can be a
347 * no-op if no per-expression behavior is needed.
348 **********************************************************************/
350 void *context);
352 void *context);
353
354/*
355 * As in nodeFuncs.h, we respectfully decline to support the C standard's
356 * position that a pointer to struct is incompatible with "void *". Instead,
357 * silence related compiler warnings using casts in this macro wrapper.
358 */
359#define plpgsql_statement_tree_walker(s, sw, ew, c) \
360 plpgsql_statement_tree_walker_impl(s, (plpgsql_stmt_walker_callback) (sw), \
361 (plpgsql_expr_walker_callback) (ew), c)
362
363static void
365 plpgsql_stmt_walker_callback stmt_callback,
366 plpgsql_expr_walker_callback expr_callback,
367 void *context)
368{
369#define S_WALK(st) stmt_callback(st, context)
370#define E_WALK(ex) expr_callback(ex, context)
371#define S_LIST_WALK(lst) foreach_ptr(PLpgSQL_stmt, st, lst) S_WALK(st)
372#define E_LIST_WALK(lst) foreach_ptr(PLpgSQL_expr, ex, lst) E_WALK(ex)
373
374 switch (stmt->cmd_type)
375 {
377 {
379
380 S_LIST_WALK(bstmt->body);
381 if (bstmt->exceptions)
382 {
384 {
385 /* conditions list has no interesting sub-structure */
386 S_LIST_WALK(exc->action);
387 }
388 }
389 break;
390 }
392 {
394
395 E_WALK(astmt->expr);
396 break;
397 }
398 case PLPGSQL_STMT_IF:
399 {
401
402 E_WALK(ifstmt->cond);
403 S_LIST_WALK(ifstmt->then_body);
404 foreach_ptr(PLpgSQL_if_elsif, elif, ifstmt->elsif_list)
405 {
406 E_WALK(elif->cond);
407 S_LIST_WALK(elif->stmts);
408 }
409 S_LIST_WALK(ifstmt->else_body);
410 break;
411 }
413 {
415
416 E_WALK(cstmt->t_expr);
418 {
419 E_WALK(cwt->expr);
420 S_LIST_WALK(cwt->stmts);
421 }
422 S_LIST_WALK(cstmt->else_stmts);
423 break;
424 }
426 {
428
429 S_LIST_WALK(lstmt->body);
430 break;
431 }
433 {
435
436 E_WALK(wstmt->cond);
437 S_LIST_WALK(wstmt->body);
438 break;
439 }
441 {
443
444 E_WALK(fori->lower);
445 E_WALK(fori->upper);
446 E_WALK(fori->step);
447 S_LIST_WALK(fori->body);
448 break;
449 }
451 {
453
454 S_LIST_WALK(fors->body);
455 E_WALK(fors->query);
456 break;
457 }
459 {
461
462 S_LIST_WALK(forc->body);
463 E_WALK(forc->argquery);
464 break;
465 }
467 {
469
470 E_WALK(fstmt->expr);
471 S_LIST_WALK(fstmt->body);
472 break;
473 }
475 {
477
478 E_WALK(estmt->cond);
479 break;
480 }
482 {
484
485 E_WALK(rstmt->expr);
486 break;
487 }
489 {
491
492 E_WALK(rstmt->expr);
493 break;
494 }
496 {
498
499 E_WALK(rstmt->query);
500 E_WALK(rstmt->dynquery);
501 E_LIST_WALK(rstmt->params);
502 break;
503 }
505 {
507
508 E_LIST_WALK(rstmt->params);
510 {
511 E_WALK(opt->expr);
512 }
513 break;
514 }
516 {
518
519 E_WALK(astmt->cond);
520 E_WALK(astmt->message);
521 break;
522 }
524 {
526
527 E_WALK(xstmt->sqlstmt);
528 break;
529 }
531 {
533
534 E_WALK(dstmt->query);
535 E_LIST_WALK(dstmt->params);
536 break;
537 }
539 {
541
542 S_LIST_WALK(dstmt->body);
543 E_WALK(dstmt->query);
544 E_LIST_WALK(dstmt->params);
545 break;
546 }
548 {
549 /* no interesting sub-structure */
550 break;
551 }
553 {
555
556 E_WALK(ostmt->argquery);
557 E_WALK(ostmt->query);
558 E_WALK(ostmt->dynquery);
559 E_LIST_WALK(ostmt->params);
560 break;
561 }
563 {
565
566 E_WALK(fstmt->expr);
567 break;
568 }
570 {
571 /* no interesting sub-structure */
572 break;
573 }
575 {
577
578 E_WALK(pstmt->expr);
579 break;
580 }
582 {
584
585 E_WALK(cstmt->expr);
586 break;
587 }
590 {
591 /* no interesting sub-structure */
592 break;
593 }
594 default:
595 elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
596 break;
597 }
598}
599
600
601/**********************************************************************
602 * Mark assignment source expressions that have local target variables,
603 * that is, the target variable is declared within the exception block
604 * most closely containing the assignment itself. (Such target variables
605 * need not be preserved if the assignment's source expression raises an
606 * error, since the variable will no longer be accessible afterwards.
607 * Detecting this allows better optimization.)
608 *
609 * This code need not be called if the plpgsql function contains no exception
610 * blocks, because mark_expr_as_assignment_source will have set all the flags
611 * to true already. Also, we need not reconsider default-value expressions
612 * for variables, because variable declarations are necessarily within the
613 * nearest exception block. (In DECLARE ... BEGIN ... EXCEPTION ... END, the
614 * variable initializations are done before entering the exception scope.)
615 *
616 * Within the recursion, local_dnos is a Bitmapset of dnos of variables
617 * known to be declared within the current exception level.
618 **********************************************************************/
619static void mark_stmt(PLpgSQL_stmt *stmt, Bitmapset *local_dnos);
620static void mark_expr(PLpgSQL_expr *expr, Bitmapset *local_dnos);
621
622static void
624{
625 if (stmt == NULL)
626 return;
627 if (stmt->cmd_type == PLPGSQL_STMT_BLOCK)
628 {
630
631 if (block->exceptions)
632 {
633 /*
634 * The block creates a new exception scope, so variables declared
635 * at outer levels are nonlocal. For that matter, so are any
636 * variables declared in the block's DECLARE section. Hence, we
637 * must pass down empty local_dnos.
638 */
640 }
641 else
642 {
643 /*
644 * Otherwise, the block does not create a new exception scope, and
645 * any variables it declares can also be considered local within
646 * it. Note that only initializable datum types (VAR, REC) are
647 * included in initvarnos; but that's sufficient for our purposes.
648 */
649 local_dnos = bms_copy(local_dnos);
650 for (int i = 0; i < block->n_initvars; i++)
651 local_dnos = bms_add_member(local_dnos, block->initvarnos[i]);
653 local_dnos);
654 bms_free(local_dnos);
655 }
656 }
657 else
659}
660
661static void
663{
664 /*
665 * If this expression has an assignment target, check whether the target
666 * is local, and mark the expression accordingly.
667 */
668 if (expr && expr->target_param >= 0)
669 expr->target_is_local = bms_is_member(expr->target_param, local_dnos);
670}
671
672void
674{
675 Bitmapset *local_dnos;
676
677 /* Function parameters can be treated as local targets at outer level */
678 local_dnos = NULL;
679 for (int i = 0; i < func->fn_nargs; i++)
680 local_dnos = bms_add_member(local_dnos, func->fn_argvarnos[i]);
681 mark_stmt((PLpgSQL_stmt *) func->action, local_dnos);
682 bms_free(local_dnos);
683}
684
685
686/**********************************************************************
687 * Release memory when a PL/pgSQL function is no longer needed
688 *
689 * This code only needs to deal with cleaning up PLpgSQL_expr nodes,
690 * which may contain references to saved SPI Plans that must be freed.
691 * The function tree itself, along with subsidiary data, is freed in
692 * one swoop by freeing the function's permanent memory context.
693 **********************************************************************/
694static void free_stmt(PLpgSQL_stmt *stmt, void *context);
695static void free_expr(PLpgSQL_expr *expr, void *context);
696
697static void
699{
700 if (stmt == NULL)
701 return;
703}
704
705static void
706free_expr(PLpgSQL_expr *expr, void *context)
707{
708 if (expr && expr->plan)
709 {
710 SPI_freeplan(expr->plan);
711 expr->plan = NULL;
712 }
713}
714
715void
717{
718 int i;
719
720 /* Better not call this on an in-use function */
721 Assert(func->cfunc.use_count == 0);
722
723 /* Release plans associated with variable declarations */
724 for (i = 0; i < func->ndatums; i++)
725 {
726 PLpgSQL_datum *d = func->datums[i];
727
728 switch (d->dtype)
729 {
732 {
733 PLpgSQL_var *var = (PLpgSQL_var *) d;
734
735 free_expr(var->default_val, NULL);
737 }
738 break;
740 break;
742 {
743 PLpgSQL_rec *rec = (PLpgSQL_rec *) d;
744
745 free_expr(rec->default_val, NULL);
746 }
747 break;
749 break;
750 default:
751 elog(ERROR, "unrecognized data type: %d", d->dtype);
752 }
753 }
754 func->ndatums = 0;
755
756 /* Release plans in statement tree */
757 free_stmt((PLpgSQL_stmt *) func->action, NULL);
758 func->action = NULL;
759
760 /*
761 * And finally, release all memory except the PLpgSQL_function struct
762 * itself (which has to be kept around because there may be multiple
763 * fn_extra pointers to it).
764 */
765 if (func->fn_cxt)
767 func->fn_cxt = NULL;
768}
769
770/* Deletion callback used by funccache.c */
771void
773{
775}
776
777
778/**********************************************************************
779 * Debug functions for analyzing the compiled code
780 *
781 * Sadly, there doesn't seem to be any way to let plpgsql_statement_tree_walker
782 * bear some of the burden for this.
783 **********************************************************************/
784static int dump_indent;
785
786static void dump_ind(void);
787static void dump_stmt(PLpgSQL_stmt *stmt);
788static void dump_block(PLpgSQL_stmt_block *block);
790static void dump_if(PLpgSQL_stmt_if *stmt);
791static void dump_case(PLpgSQL_stmt_case *stmt);
792static void dump_loop(PLpgSQL_stmt_loop *stmt);
794static void dump_fori(PLpgSQL_stmt_fori *stmt);
795static void dump_fors(PLpgSQL_stmt_fors *stmt);
796static void dump_forc(PLpgSQL_stmt_forc *stmt);
798static void dump_exit(PLpgSQL_stmt_exit *stmt);
808static void dump_open(PLpgSQL_stmt_open *stmt);
813static void dump_call(PLpgSQL_stmt_call *stmt);
816static void dump_expr(PLpgSQL_expr *expr);
817
818
819static void
821{
822 int i;
823
824 for (i = 0; i < dump_indent; i++)
825 printf(" ");
826}
827
828static void
830{
831 printf("%3d:", stmt->lineno);
832 switch (stmt->cmd_type)
833 {
836 break;
839 break;
840 case PLPGSQL_STMT_IF:
842 break;
845 break;
848 break;
851 break;
854 break;
857 break;
860 break;
863 break;
866 break;
869 break;
872 break;
875 break;
878 break;
881 break;
884 break;
887 break;
890 break;
893 break;
896 break;
899 break;
902 break;
905 break;
908 break;
911 break;
914 break;
915 default:
916 elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
917 break;
918 }
919}
920
921static void
923{
924 ListCell *s;
925
926 dump_indent += 2;
927 foreach(s, stmts)
929 dump_indent -= 2;
930}
931
932static void
934{
935 char *name;
936
937 if (block->label == NULL)
938 name = "*unnamed*";
939 else
940 name = block->label;
941
942 dump_ind();
943 printf("BLOCK <<%s>>\n", name);
944
945 dump_stmts(block->body);
946
947 if (block->exceptions)
948 {
949 ListCell *e;
950
951 foreach(e, block->exceptions->exc_list)
952 {
954 PLpgSQL_condition *cond;
955
956 dump_ind();
957 printf(" EXCEPTION WHEN ");
958 for (cond = exc->conditions; cond; cond = cond->next)
959 {
960 if (cond != exc->conditions)
961 printf(" OR ");
962 printf("%s", cond->condname);
963 }
964 printf(" THEN\n");
965 dump_stmts(exc->action);
966 }
967 }
968
969 dump_ind();
970 printf(" END -- %s\n", name);
971}
972
973static void
975{
976 dump_ind();
977 printf("ASSIGN var %d := ", stmt->varno);
978 dump_expr(stmt->expr);
979 printf("\n");
980}
981
982static void
984{
985 ListCell *l;
986
987 dump_ind();
988 printf("IF ");
989 dump_expr(stmt->cond);
990 printf(" THEN\n");
991 dump_stmts(stmt->then_body);
992 foreach(l, stmt->elsif_list)
993 {
995
996 dump_ind();
997 printf(" ELSIF ");
998 dump_expr(elif->cond);
999 printf(" THEN\n");
1000 dump_stmts(elif->stmts);
1001 }
1002 if (stmt->else_body != NIL)
1003 {
1004 dump_ind();
1005 printf(" ELSE\n");
1006 dump_stmts(stmt->else_body);
1007 }
1008 dump_ind();
1009 printf(" ENDIF\n");
1010}
1011
1012static void
1014{
1015 ListCell *l;
1016
1017 dump_ind();
1018 printf("CASE %d ", stmt->t_varno);
1019 if (stmt->t_expr)
1020 dump_expr(stmt->t_expr);
1021 printf("\n");
1022 dump_indent += 6;
1023 foreach(l, stmt->case_when_list)
1024 {
1026
1027 dump_ind();
1028 printf("WHEN ");
1029 dump_expr(cwt->expr);
1030 printf("\n");
1031 dump_ind();
1032 printf("THEN\n");
1033 dump_indent += 2;
1034 dump_stmts(cwt->stmts);
1035 dump_indent -= 2;
1036 }
1037 if (stmt->have_else)
1038 {
1039 dump_ind();
1040 printf("ELSE\n");
1041 dump_indent += 2;
1042 dump_stmts(stmt->else_stmts);
1043 dump_indent -= 2;
1044 }
1045 dump_indent -= 6;
1046 dump_ind();
1047 printf(" ENDCASE\n");
1048}
1049
1050static void
1052{
1053 dump_ind();
1054 printf("LOOP\n");
1055
1056 dump_stmts(stmt->body);
1057
1058 dump_ind();
1059 printf(" ENDLOOP\n");
1060}
1061
1062static void
1064{
1065 dump_ind();
1066 printf("WHILE ");
1067 dump_expr(stmt->cond);
1068 printf("\n");
1069
1070 dump_stmts(stmt->body);
1071
1072 dump_ind();
1073 printf(" ENDWHILE\n");
1074}
1075
1076static void
1078{
1079 dump_ind();
1080 printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
1081
1082 dump_indent += 2;
1083 dump_ind();
1084 printf(" lower = ");
1085 dump_expr(stmt->lower);
1086 printf("\n");
1087 dump_ind();
1088 printf(" upper = ");
1089 dump_expr(stmt->upper);
1090 printf("\n");
1091 if (stmt->step)
1092 {
1093 dump_ind();
1094 printf(" step = ");
1095 dump_expr(stmt->step);
1096 printf("\n");
1097 }
1098 dump_indent -= 2;
1099
1100 dump_stmts(stmt->body);
1101
1102 dump_ind();
1103 printf(" ENDFORI\n");
1104}
1105
1106static void
1108{
1109 dump_ind();
1110 printf("FORS %s ", stmt->var->refname);
1111 dump_expr(stmt->query);
1112 printf("\n");
1113
1114 dump_stmts(stmt->body);
1115
1116 dump_ind();
1117 printf(" ENDFORS\n");
1118}
1119
1120static void
1122{
1123 dump_ind();
1124 printf("FORC %s ", stmt->var->refname);
1125 printf("curvar=%d\n", stmt->curvar);
1126
1127 dump_indent += 2;
1128 if (stmt->argquery != NULL)
1129 {
1130 dump_ind();
1131 printf(" arguments = ");
1132 dump_expr(stmt->argquery);
1133 printf("\n");
1134 }
1135 dump_indent -= 2;
1136
1137 dump_stmts(stmt->body);
1138
1139 dump_ind();
1140 printf(" ENDFORC\n");
1141}
1142
1143static void
1145{
1146 dump_ind();
1147 printf("FOREACHA var %d ", stmt->varno);
1148 if (stmt->slice != 0)
1149 printf("SLICE %d ", stmt->slice);
1150 printf("IN ");
1151 dump_expr(stmt->expr);
1152 printf("\n");
1153
1154 dump_stmts(stmt->body);
1155
1156 dump_ind();
1157 printf(" ENDFOREACHA");
1158}
1159
1160static void
1162{
1163 dump_ind();
1164 printf("OPEN curvar=%d\n", stmt->curvar);
1165
1166 dump_indent += 2;
1167 if (stmt->argquery != NULL)
1168 {
1169 dump_ind();
1170 printf(" arguments = '");
1171 dump_expr(stmt->argquery);
1172 printf("'\n");
1173 }
1174 if (stmt->query != NULL)
1175 {
1176 dump_ind();
1177 printf(" query = '");
1178 dump_expr(stmt->query);
1179 printf("'\n");
1180 }
1181 if (stmt->dynquery != NULL)
1182 {
1183 dump_ind();
1184 printf(" execute = '");
1185 dump_expr(stmt->dynquery);
1186 printf("'\n");
1187
1188 if (stmt->params != NIL)
1189 {
1190 ListCell *lc;
1191 int i;
1192
1193 dump_indent += 2;
1194 dump_ind();
1195 printf(" USING\n");
1196 dump_indent += 2;
1197 i = 1;
1198 foreach(lc, stmt->params)
1199 {
1200 dump_ind();
1201 printf(" parameter $%d: ", i++);
1202 dump_expr((PLpgSQL_expr *) lfirst(lc));
1203 printf("\n");
1204 }
1205 dump_indent -= 4;
1206 }
1207 }
1208 dump_indent -= 2;
1209}
1210
1211static void
1213{
1214 dump_ind();
1215
1216 if (!stmt->is_move)
1217 {
1218 printf("FETCH curvar=%d\n", stmt->curvar);
1220
1221 dump_indent += 2;
1222 if (stmt->target != NULL)
1223 {
1224 dump_ind();
1225 printf(" target = %d %s\n",
1226 stmt->target->dno, stmt->target->refname);
1227 }
1228 dump_indent -= 2;
1229 }
1230 else
1231 {
1232 printf("MOVE curvar=%d\n", stmt->curvar);
1234 }
1235}
1236
1237static void
1239{
1240 dump_indent += 2;
1241 dump_ind();
1242 switch (stmt->direction)
1243 {
1244 case FETCH_FORWARD:
1245 printf(" FORWARD ");
1246 break;
1247 case FETCH_BACKWARD:
1248 printf(" BACKWARD ");
1249 break;
1250 case FETCH_ABSOLUTE:
1251 printf(" ABSOLUTE ");
1252 break;
1253 case FETCH_RELATIVE:
1254 printf(" RELATIVE ");
1255 break;
1256 default:
1257 printf("??? unknown cursor direction %d", stmt->direction);
1258 }
1259
1260 if (stmt->expr)
1261 {
1262 dump_expr(stmt->expr);
1263 printf("\n");
1264 }
1265 else
1266 printf("%ld\n", stmt->how_many);
1267
1268 dump_indent -= 2;
1269}
1270
1271static void
1273{
1274 dump_ind();
1275 printf("CLOSE curvar=%d\n", stmt->curvar);
1276}
1277
1278static void
1280{
1281 dump_ind();
1282 printf("PERFORM expr = ");
1283 dump_expr(stmt->expr);
1284 printf("\n");
1285}
1286
1287static void
1289{
1290 dump_ind();
1291 printf("%s expr = ", stmt->is_call ? "CALL" : "DO");
1292 dump_expr(stmt->expr);
1293 printf("\n");
1294}
1295
1296static void
1298{
1299 dump_ind();
1300 if (stmt->chain)
1301 printf("COMMIT AND CHAIN\n");
1302 else
1303 printf("COMMIT\n");
1304}
1305
1306static void
1308{
1309 dump_ind();
1310 if (stmt->chain)
1311 printf("ROLLBACK AND CHAIN\n");
1312 else
1313 printf("ROLLBACK\n");
1314}
1315
1316static void
1318{
1319 dump_ind();
1320 printf("%s", stmt->is_exit ? "EXIT" : "CONTINUE");
1321 if (stmt->label != NULL)
1322 printf(" label='%s'", stmt->label);
1323 if (stmt->cond != NULL)
1324 {
1325 printf(" WHEN ");
1326 dump_expr(stmt->cond);
1327 }
1328 printf("\n");
1329}
1330
1331static void
1333{
1334 dump_ind();
1335 printf("RETURN ");
1336 if (stmt->retvarno >= 0)
1337 printf("variable %d", stmt->retvarno);
1338 else if (stmt->expr != NULL)
1339 dump_expr(stmt->expr);
1340 else
1341 printf("NULL");
1342 printf("\n");
1343}
1344
1345static void
1347{
1348 dump_ind();
1349 printf("RETURN NEXT ");
1350 if (stmt->retvarno >= 0)
1351 printf("variable %d", stmt->retvarno);
1352 else if (stmt->expr != NULL)
1353 dump_expr(stmt->expr);
1354 else
1355 printf("NULL");
1356 printf("\n");
1357}
1358
1359static void
1361{
1362 dump_ind();
1363 if (stmt->query)
1364 {
1365 printf("RETURN QUERY ");
1366 dump_expr(stmt->query);
1367 printf("\n");
1368 }
1369 else
1370 {
1371 printf("RETURN QUERY EXECUTE ");
1372 dump_expr(stmt->dynquery);
1373 printf("\n");
1374 if (stmt->params != NIL)
1375 {
1376 ListCell *lc;
1377 int i;
1378
1379 dump_indent += 2;
1380 dump_ind();
1381 printf(" USING\n");
1382 dump_indent += 2;
1383 i = 1;
1384 foreach(lc, stmt->params)
1385 {
1386 dump_ind();
1387 printf(" parameter $%d: ", i++);
1388 dump_expr((PLpgSQL_expr *) lfirst(lc));
1389 printf("\n");
1390 }
1391 dump_indent -= 4;
1392 }
1393 }
1394}
1395
1396static void
1398{
1399 ListCell *lc;
1400 int i = 0;
1401
1402 dump_ind();
1403 printf("RAISE level=%d", stmt->elog_level);
1404 if (stmt->condname)
1405 printf(" condname='%s'", stmt->condname);
1406 if (stmt->message)
1407 printf(" message='%s'", stmt->message);
1408 printf("\n");
1409 dump_indent += 2;
1410 foreach(lc, stmt->params)
1411 {
1412 dump_ind();
1413 printf(" parameter %d: ", i++);
1414 dump_expr((PLpgSQL_expr *) lfirst(lc));
1415 printf("\n");
1416 }
1417 if (stmt->options)
1418 {
1419 dump_ind();
1420 printf(" USING\n");
1421 dump_indent += 2;
1422 foreach(lc, stmt->options)
1423 {
1425
1426 dump_ind();
1427 switch (opt->opt_type)
1428 {
1430 printf(" ERRCODE = ");
1431 break;
1433 printf(" MESSAGE = ");
1434 break;
1436 printf(" DETAIL = ");
1437 break;
1439 printf(" HINT = ");
1440 break;
1442 printf(" COLUMN = ");
1443 break;
1445 printf(" CONSTRAINT = ");
1446 break;
1448 printf(" DATATYPE = ");
1449 break;
1451 printf(" TABLE = ");
1452 break;
1454 printf(" SCHEMA = ");
1455 break;
1456 }
1457 dump_expr(opt->expr);
1458 printf("\n");
1459 }
1460 dump_indent -= 2;
1461 }
1462 dump_indent -= 2;
1463}
1464
1465static void
1467{
1468 dump_ind();
1469 printf("ASSERT ");
1470 dump_expr(stmt->cond);
1471 printf("\n");
1472
1473 dump_indent += 2;
1474 if (stmt->message != NULL)
1475 {
1476 dump_ind();
1477 printf(" MESSAGE = ");
1478 dump_expr(stmt->message);
1479 printf("\n");
1480 }
1481 dump_indent -= 2;
1482}
1483
1484static void
1486{
1487 dump_ind();
1488 printf("EXECSQL ");
1489 dump_expr(stmt->sqlstmt);
1490 printf("\n");
1491
1492 dump_indent += 2;
1493 if (stmt->target != NULL)
1494 {
1495 dump_ind();
1496 printf(" INTO%s target = %d %s\n",
1497 stmt->strict ? " STRICT" : "",
1498 stmt->target->dno, stmt->target->refname);
1499 }
1500 dump_indent -= 2;
1501}
1502
1503static void
1505{
1506 dump_ind();
1507 printf("EXECUTE ");
1508 dump_expr(stmt->query);
1509 printf("\n");
1510
1511 dump_indent += 2;
1512 if (stmt->target != NULL)
1513 {
1514 dump_ind();
1515 printf(" INTO%s target = %d %s\n",
1516 stmt->strict ? " STRICT" : "",
1517 stmt->target->dno, stmt->target->refname);
1518 }
1519 if (stmt->params != NIL)
1520 {
1521 ListCell *lc;
1522 int i;
1523
1524 dump_ind();
1525 printf(" USING\n");
1526 dump_indent += 2;
1527 i = 1;
1528 foreach(lc, stmt->params)
1529 {
1530 dump_ind();
1531 printf(" parameter %d: ", i++);
1532 dump_expr((PLpgSQL_expr *) lfirst(lc));
1533 printf("\n");
1534 }
1535 dump_indent -= 2;
1536 }
1537 dump_indent -= 2;
1538}
1539
1540static void
1542{
1543 dump_ind();
1544 printf("FORS %s EXECUTE ", stmt->var->refname);
1545 dump_expr(stmt->query);
1546 printf("\n");
1547 if (stmt->params != NIL)
1548 {
1549 ListCell *lc;
1550 int i;
1551
1552 dump_indent += 2;
1553 dump_ind();
1554 printf(" USING\n");
1555 dump_indent += 2;
1556 i = 1;
1557 foreach(lc, stmt->params)
1558 {
1559 dump_ind();
1560 printf(" parameter $%d: ", i++);
1561 dump_expr((PLpgSQL_expr *) lfirst(lc));
1562 printf("\n");
1563 }
1564 dump_indent -= 4;
1565 }
1566 dump_stmts(stmt->body);
1567 dump_ind();
1568 printf(" ENDFORS\n");
1569}
1570
1571static void
1573{
1574 ListCell *lc;
1575
1576 dump_ind();
1577 printf("GET %s DIAGNOSTICS ", stmt->is_stacked ? "STACKED" : "CURRENT");
1578 foreach(lc, stmt->diag_items)
1579 {
1580 PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
1581
1582 if (lc != list_head(stmt->diag_items))
1583 printf(", ");
1584
1585 printf("{var %d} = %s", diag_item->target,
1586 plpgsql_getdiag_kindname(diag_item->kind));
1587 }
1588 printf("\n");
1589}
1590
1591static void
1593{
1594 printf("'%s'", expr->query);
1595 if (expr->target_param >= 0)
1596 printf(" target %d%s", expr->target_param,
1597 expr->target_is_local ? " (local)" : "");
1598}
1599
1600void
1602{
1603 int i;
1604 PLpgSQL_datum *d;
1605
1606 printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
1607 func->fn_signature);
1608
1609 printf("\nFunction's data area:\n");
1610 for (i = 0; i < func->ndatums; i++)
1611 {
1612 d = func->datums[i];
1613
1614 printf(" entry %d: ", i);
1615 switch (d->dtype)
1616 {
1617 case PLPGSQL_DTYPE_VAR:
1619 {
1620 PLpgSQL_var *var = (PLpgSQL_var *) d;
1621
1622 printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
1623 var->refname, var->datatype->typname,
1624 var->datatype->typoid,
1625 var->datatype->atttypmod);
1626 if (var->isconst)
1627 printf(" CONSTANT\n");
1628 if (var->notnull)
1629 printf(" NOT NULL\n");
1630 if (var->default_val != NULL)
1631 {
1632 printf(" DEFAULT ");
1633 dump_expr(var->default_val);
1634 printf("\n");
1635 }
1636 if (var->cursor_explicit_expr != NULL)
1637 {
1638 if (var->cursor_explicit_argrow >= 0)
1639 printf(" CURSOR argument row %d\n", var->cursor_explicit_argrow);
1640
1641 printf(" CURSOR IS ");
1643 printf("\n");
1644 }
1645 if (var->promise != PLPGSQL_PROMISE_NONE)
1646 printf(" PROMISE %d\n",
1647 (int) var->promise);
1648 }
1649 break;
1650 case PLPGSQL_DTYPE_ROW:
1651 {
1652 PLpgSQL_row *row = (PLpgSQL_row *) d;
1653
1654 printf("ROW %-16s fields", row->refname);
1655 for (int j = 0; j < row->nfields; j++)
1656 {
1657 printf(" %s=var %d", row->fieldnames[j],
1658 row->varnos[j]);
1659 }
1660 printf("\n");
1661 }
1662 break;
1663 case PLPGSQL_DTYPE_REC:
1664 printf("REC %-16s typoid %u\n",
1665 ((PLpgSQL_rec *) d)->refname,
1666 ((PLpgSQL_rec *) d)->rectypeid);
1667 if (((PLpgSQL_rec *) d)->isconst)
1668 printf(" CONSTANT\n");
1669 if (((PLpgSQL_rec *) d)->notnull)
1670 printf(" NOT NULL\n");
1671 if (((PLpgSQL_rec *) d)->default_val != NULL)
1672 {
1673 printf(" DEFAULT ");
1674 dump_expr(((PLpgSQL_rec *) d)->default_val);
1675 printf("\n");
1676 }
1677 break;
1679 printf("RECFIELD %-16s of REC %d\n",
1680 ((PLpgSQL_recfield *) d)->fieldname,
1681 ((PLpgSQL_recfield *) d)->recparentno);
1682 break;
1683 default:
1684 printf("??? unknown data type %d\n", d->dtype);
1685 }
1686 }
1687 printf("\nFunction's statements:\n");
1688
1689 dump_indent = 0;
1690 printf("%3d:", func->action->lineno);
1691 dump_block(func->action);
1692 printf("\nEnd of execution tree of function %s\n\n", func->fn_signature);
1693 fflush(stdout);
1694}
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:122
#define _(x)
Definition: elog.c:91
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
Assert(PointerIsAligned(start, uint64))
#define stmt
Definition: indent_codes.h:59
#define ifstmt
Definition: indent_codes.h:56
int j
Definition: isn.c:78
int i
Definition: isn.c:77
void * palloc(Size size)
Definition: mcxt.c:1943
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:485
@ FETCH_RELATIVE
Definition: parsenodes.h:3417
@ FETCH_ABSOLUTE
Definition: parsenodes.h:3416
@ FETCH_FORWARD
Definition: parsenodes.h:3413
@ FETCH_BACKWARD
Definition: parsenodes.h:3414
static char * label
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
#define foreach_ptr(type, var, lst)
Definition: pg_list.h:469
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static void dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
Definition: pl_funcs.c:1504
static void dump_return_next(PLpgSQL_stmt_return_next *stmt)
Definition: pl_funcs.c:1346
void plpgsql_ns_pop(void)
Definition: pl_funcs.c:67
void(* plpgsql_stmt_walker_callback)(PLpgSQL_stmt *stmt, void *context)
Definition: pl_funcs.c:349
static void dump_close(PLpgSQL_stmt_close *stmt)
Definition: pl_funcs.c:1272
static void dump_perform(PLpgSQL_stmt_perform *stmt)
Definition: pl_funcs.c:1279
static void dump_if(PLpgSQL_stmt_if *stmt)
Definition: pl_funcs.c:983
static void dump_fetch(PLpgSQL_stmt_fetch *stmt)
Definition: pl_funcs.c:1212
void plpgsql_ns_init(void)
Definition: pl_funcs.c:43
static void dump_execsql(PLpgSQL_stmt_execsql *stmt)
Definition: pl_funcs.c:1485
static int dump_indent
Definition: pl_funcs.c:784
static void dump_case(PLpgSQL_stmt_case *stmt)
Definition: pl_funcs.c:1013
#define E_LIST_WALK(lst)
PLpgSQL_nsitem * plpgsql_ns_find_nearest_loop(PLpgSQL_nsitem *ns_cur)
Definition: pl_funcs.c:214
static void dump_open(PLpgSQL_stmt_open *stmt)
Definition: pl_funcs.c:1161
PLpgSQL_nsitem * plpgsql_ns_lookup_label(PLpgSQL_nsitem *ns_cur, const char *name)
Definition: pl_funcs.c:195
static void dump_assign(PLpgSQL_stmt_assign *stmt)
Definition: pl_funcs.c:974
static void dump_stmts(List *stmts)
Definition: pl_funcs.c:922
static void plpgsql_statement_tree_walker_impl(PLpgSQL_stmt *stmt, plpgsql_stmt_walker_callback stmt_callback, plpgsql_expr_walker_callback expr_callback, void *context)
Definition: pl_funcs.c:364
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
void plpgsql_delete_callback(CachedFunction *cfunc)
Definition: pl_funcs.c:772
static void dump_cursor_direction(PLpgSQL_stmt_fetch *stmt)
Definition: pl_funcs.c:1238
void plpgsql_dumptree(PLpgSQL_function *func)
Definition: pl_funcs.c:1601
static void mark_stmt(PLpgSQL_stmt *stmt, Bitmapset *local_dnos)
Definition: pl_funcs.c:623
#define S_LIST_WALK(lst)
static PLpgSQL_nsitem * ns_top
Definition: pl_funcs.c:35
#define E_WALK(ex)
const char * plpgsql_stmt_typename(PLpgSQL_stmt *stmt)
Definition: pl_funcs.c:232
void(* plpgsql_expr_walker_callback)(PLpgSQL_expr *expr, void *context)
Definition: pl_funcs.c:351
static void dump_loop(PLpgSQL_stmt_loop *stmt)
Definition: pl_funcs.c:1051
static void dump_raise(PLpgSQL_stmt_raise *stmt)
Definition: pl_funcs.c:1397
static void dump_rollback(PLpgSQL_stmt_rollback *stmt)
Definition: pl_funcs.c:1307
void plpgsql_free_function_memory(PLpgSQL_function *func)
Definition: pl_funcs.c:716
static void dump_while(PLpgSQL_stmt_while *stmt)
Definition: pl_funcs.c:1063
static void dump_expr(PLpgSQL_expr *expr)
Definition: pl_funcs.c:1592
void plpgsql_mark_local_assignment_targets(PLpgSQL_function *func)
Definition: pl_funcs.c:673
static void dump_stmt(PLpgSQL_stmt *stmt)
Definition: pl_funcs.c:829
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
static void dump_block(PLpgSQL_stmt_block *block)
Definition: pl_funcs.c:933
static void dump_getdiag(PLpgSQL_stmt_getdiag *stmt)
Definition: pl_funcs.c:1572
static void dump_exit(PLpgSQL_stmt_exit *stmt)
Definition: pl_funcs.c:1317
static void free_stmt(PLpgSQL_stmt *stmt, void *context)
Definition: pl_funcs.c:698
static void dump_call(PLpgSQL_stmt_call *stmt)
Definition: pl_funcs.c:1288
static void dump_forc(PLpgSQL_stmt_forc *stmt)
Definition: pl_funcs.c:1121
static void dump_ind(void)
Definition: pl_funcs.c:820
static void dump_commit(PLpgSQL_stmt_commit *stmt)
Definition: pl_funcs.c:1297
static void dump_return(PLpgSQL_stmt_return *stmt)
Definition: pl_funcs.c:1332
static void free_expr(PLpgSQL_expr *expr, void *context)
Definition: pl_funcs.c:706
#define plpgsql_statement_tree_walker(s, sw, ew, c)
Definition: pl_funcs.c:359
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:54
static void dump_foreach_a(PLpgSQL_stmt_foreach_a *stmt)
Definition: pl_funcs.c:1144
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
static void dump_return_query(PLpgSQL_stmt_return_query *stmt)
Definition: pl_funcs.c:1360
static void dump_assert(PLpgSQL_stmt_assert *stmt)
Definition: pl_funcs.c:1466
static void dump_dynfors(PLpgSQL_stmt_dynfors *stmt)
Definition: pl_funcs.c:1541
const char * plpgsql_getdiag_kindname(PLpgSQL_getdiag_kind kind)
Definition: pl_funcs.c:300
static void dump_fori(PLpgSQL_stmt_fori *stmt)
Definition: pl_funcs.c:1077
static void dump_fors(PLpgSQL_stmt_fors *stmt)
Definition: pl_funcs.c:1107
static void mark_expr(PLpgSQL_expr *expr, Bitmapset *local_dnos)
Definition: pl_funcs.c:662
@ PLPGSQL_STMT_DYNFORS
Definition: plpgsql.h:123
@ PLPGSQL_STMT_FORI
Definition: plpgsql.h:111
@ PLPGSQL_STMT_FETCH
Definition: plpgsql.h:126
@ PLPGSQL_STMT_CASE
Definition: plpgsql.h:108
@ PLPGSQL_STMT_OPEN
Definition: plpgsql.h:125
@ PLPGSQL_STMT_ROLLBACK
Definition: plpgsql.h:131
@ PLPGSQL_STMT_COMMIT
Definition: plpgsql.h:130
@ PLPGSQL_STMT_RETURN_QUERY
Definition: plpgsql.h:118
@ PLPGSQL_STMT_RETURN
Definition: plpgsql.h:116
@ PLPGSQL_STMT_CLOSE
Definition: plpgsql.h:127
@ PLPGSQL_STMT_WHILE
Definition: plpgsql.h:110
@ PLPGSQL_STMT_BLOCK
Definition: plpgsql.h:105
@ PLPGSQL_STMT_FORS
Definition: plpgsql.h:112
@ PLPGSQL_STMT_FORC
Definition: plpgsql.h:113
@ PLPGSQL_STMT_IF
Definition: plpgsql.h:107
@ PLPGSQL_STMT_PERFORM
Definition: plpgsql.h:128
@ PLPGSQL_STMT_LOOP
Definition: plpgsql.h:109
@ PLPGSQL_STMT_ASSERT
Definition: plpgsql.h:120
@ PLPGSQL_STMT_FOREACH_A
Definition: plpgsql.h:114
@ PLPGSQL_STMT_GETDIAG
Definition: plpgsql.h:124
@ PLPGSQL_STMT_RETURN_NEXT
Definition: plpgsql.h:117
@ PLPGSQL_STMT_ASSIGN
Definition: plpgsql.h:106
@ PLPGSQL_STMT_EXIT
Definition: plpgsql.h:115
@ PLPGSQL_STMT_EXECSQL
Definition: plpgsql.h:121
@ PLPGSQL_STMT_RAISE
Definition: plpgsql.h:119
@ PLPGSQL_STMT_CALL
Definition: plpgsql.h:129
@ PLPGSQL_STMT_DYNEXECUTE
Definition: plpgsql.h:122
@ PLPGSQL_RAISEOPTION_COLUMN
Definition: plpgsql.h:174
@ PLPGSQL_RAISEOPTION_TABLE
Definition: plpgsql.h:177
@ PLPGSQL_RAISEOPTION_SCHEMA
Definition: plpgsql.h:178
@ PLPGSQL_RAISEOPTION_CONSTRAINT
Definition: plpgsql.h:175
@ PLPGSQL_RAISEOPTION_DETAIL
Definition: plpgsql.h:172
@ PLPGSQL_RAISEOPTION_MESSAGE
Definition: plpgsql.h:171
@ PLPGSQL_RAISEOPTION_HINT
Definition: plpgsql.h:173
@ PLPGSQL_RAISEOPTION_ERRCODE
Definition: plpgsql.h:170
@ PLPGSQL_RAISEOPTION_DATATYPE
Definition: plpgsql.h:176
@ PLPGSQL_PROMISE_NONE
Definition: plpgsql.h:76
PLpgSQL_label_type
Definition: plpgsql.h:53
@ PLPGSQL_LABEL_LOOP
Definition: plpgsql.h:55
@ PLPGSQL_DTYPE_ROW
Definition: plpgsql.h:65
@ PLPGSQL_DTYPE_PROMISE
Definition: plpgsql.h:68
@ PLPGSQL_DTYPE_RECFIELD
Definition: plpgsql.h:67
@ PLPGSQL_DTYPE_REC
Definition: plpgsql.h:66
@ PLPGSQL_DTYPE_VAR
Definition: plpgsql.h:64
PLpgSQL_nsitem_type
Definition: plpgsql.h:43
@ PLPGSQL_NSTYPE_VAR
Definition: plpgsql.h:45
@ PLPGSQL_NSTYPE_LABEL
Definition: plpgsql.h:44
PLpgSQL_getdiag_kind
Definition: plpgsql.h:149
@ PLPGSQL_GETDIAG_ERROR_DETAIL
Definition: plpgsql.h:154
@ PLPGSQL_GETDIAG_SCHEMA_NAME
Definition: plpgsql.h:162
@ PLPGSQL_GETDIAG_MESSAGE_TEXT
Definition: plpgsql.h:160
@ PLPGSQL_GETDIAG_DATATYPE_NAME
Definition: plpgsql.h:159
@ PLPGSQL_GETDIAG_TABLE_NAME
Definition: plpgsql.h:161
@ PLPGSQL_GETDIAG_CONSTRAINT_NAME
Definition: plpgsql.h:158
@ PLPGSQL_GETDIAG_COLUMN_NAME
Definition: plpgsql.h:157
@ PLPGSQL_GETDIAG_ROW_COUNT
Definition: plpgsql.h:150
@ PLPGSQL_GETDIAG_RETURNED_SQLSTATE
Definition: plpgsql.h:156
@ PLPGSQL_GETDIAG_CONTEXT
Definition: plpgsql.h:152
@ PLPGSQL_GETDIAG_ERROR_HINT
Definition: plpgsql.h:155
@ PLPGSQL_GETDIAG_ERROR_CONTEXT
Definition: plpgsql.h:153
@ PLPGSQL_GETDIAG_ROUTINE_OID
Definition: plpgsql.h:151
#define printf(...)
Definition: port.h:245
e
Definition: preproc-init.c:82
int SPI_freeplan(SPIPlanPtr plan)
Definition: spi.c:1026
uint64 use_count
Definition: funccache.h:117
Definition: pg_list.h:54
PLpgSQL_expr * expr
Definition: plpgsql.h:661
char * condname
Definition: plpgsql.h:495
struct PLpgSQL_condition * next
Definition: plpgsql.h:496
PLpgSQL_datum_type dtype
Definition: plpgsql.h:300
PLpgSQL_getdiag_kind kind
Definition: plpgsql.h:600
PLpgSQL_condition * conditions
Definition: plpgsql.h:518
int target_param
Definition: plpgsql.h:244
SPIPlanPtr plan
Definition: plpgsql.h:251
bool target_is_local
Definition: plpgsql.h:245
char * query
Definition: plpgsql.h:232
CachedFunction cfunc
Definition: plpgsql.h:960
MemoryContext fn_cxt
Definition: plpgsql.h:966
int fn_argvarnos[FUNC_MAX_ARGS]
Definition: plpgsql.h:978
PLpgSQL_stmt_block * action
Definition: plpgsql.h:998
PLpgSQL_datum ** datums
Definition: plpgsql.h:994
char * fn_signature
Definition: plpgsql.h:962
PLpgSQL_expr * cond
Definition: plpgsql.h:636
List * stmts
Definition: plpgsql.h:637
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: plpgsql.h:470
struct PLpgSQL_nsitem * prev
Definition: plpgsql.h:469
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:462
PLpgSQL_raise_option_type opt_type
Definition: plpgsql.h:898
PLpgSQL_expr * expr
Definition: plpgsql.h:899
PLpgSQL_datum_type dtype
Definition: plpgsql.h:414
PLpgSQL_expr * default_val
Definition: plpgsql.h:420
int * varnos
Definition: plpgsql.h:406
char * refname
Definition: plpgsql.h:390
char ** fieldnames
Definition: plpgsql.h:405
int nfields
Definition: plpgsql.h:404
PLpgSQL_expr * cond
Definition: plpgsql.h:910
PLpgSQL_expr * message
Definition: plpgsql.h:911
PLpgSQL_expr * expr
Definition: plpgsql.h:546
PLpgSQL_exception_block * exceptions
Definition: plpgsql.h:534
PLpgSQL_expr * expr
Definition: plpgsql.h:568
List * case_when_list
Definition: plpgsql.h:650
List * else_stmts
Definition: plpgsql.h:652
PLpgSQL_expr * t_expr
Definition: plpgsql.h:648
PLpgSQL_expr * query
Definition: plpgsql.h:938
PLpgSQL_expr * query
Definition: plpgsql.h:765
PLpgSQL_expr * sqlstmt
Definition: plpgsql.h:922
PLpgSQL_expr * cond
Definition: plpgsql.h:838
PLpgSQL_expr * expr
Definition: plpgsql.h:812
PLpgSQL_expr * argquery
Definition: plpgsql.h:750
PLpgSQL_expr * expr
Definition: plpgsql.h:780
PLpgSQL_expr * upper
Definition: plpgsql.h:701
PLpgSQL_expr * lower
Definition: plpgsql.h:700
PLpgSQL_expr * step
Definition: plpgsql.h:702
PLpgSQL_expr * query
Definition: plpgsql.h:734
PLpgSQL_expr * argquery
Definition: plpgsql.h:794
PLpgSQL_expr * dynquery
Definition: plpgsql.h:796
PLpgSQL_expr * query
Definition: plpgsql.h:795
PLpgSQL_expr * expr
Definition: plpgsql.h:557
PLpgSQL_expr * expr
Definition: plpgsql.h:861
PLpgSQL_expr * dynquery
Definition: plpgsql.h:874
PLpgSQL_expr * query
Definition: plpgsql.h:873
PLpgSQL_expr * expr
Definition: plpgsql.h:849
PLpgSQL_expr * cond
Definition: plpgsql.h:686
Oid typoid
Definition: plpgsql.h:213
char * typname
Definition: plpgsql.h:212
int32 atttypmod
Definition: plpgsql.h:220
PLpgSQL_promise_type promise
Definition: plpgsql.h:365
int cursor_explicit_argrow
Definition: plpgsql.h:351
bool notnull
Definition: plpgsql.h:339
bool isconst
Definition: plpgsql.h:338
PLpgSQL_expr * cursor_explicit_expr
Definition: plpgsql.h:350
PLpgSQL_type * datatype
Definition: plpgsql.h:343
PLpgSQL_expr * default_val
Definition: plpgsql.h:340
char * refname
Definition: plpgsql.h:336
const char * name