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

Generated by: LCOV version 1.13