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

Generated by: LCOV version 1.11