LCOV - code coverage report
Current view: top level - src/pl/plpgsql/src - pl_funcs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 347 1000 34.7 %
Date: 2020-06-03 10:06:28 Functions: 41 76 53.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13